Thread: Need some suggestions for cross platform code

  1. #1
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733

    Need some suggestions for cross platform code

    I have multiple functions that could use simplfying but for now I'll start with the file io related functions as I want to get rid of the need for synchronised offsets, MSW uses the OVERLAPPED structure for this, on linux however all I've found is write() and read(), both of which do not support arbitrary offsets, I theorise I could just duplicate the file descriptor but keeping in mind older systems that do not support unlimited file descriptors I decided going that route would be a bad idea, what other means would there be besides just recording the offset and putting it back after?

  2. #2
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    I think I came up with a workable solution, haven't had the chance to test it yet as I'm still cleaning up stuff that exposed the OVERLAPPED structure to the developer:

    Code:
    PAW_MIN_API pawzd pawfio_writeat( pawfio fio, pawp src, pawzd cap, pawju pos )
    {
    	if ( cap > 0 )
    	{
    		pawzu ps = sysconf( _SC_PAGE_SIZE );
    		pawju from = PawToLowerMultiple( pos, ps );
    		pawzu size = PawToUpperMultiple( cap, ps );
    		void *dest = mmap( NULL, size, PROT_WRITE, MAP_SHARED, fio, from );
    		if ( !dest ) return -1;
    		paw_cpy( dest + (pos - from), src, cap );
    		munmap( dest, size );
    		return cap;
    	}
    	return -(cap < 0);
    }
    
    PAW_MIN_API pawzd pawfio_fetchat( pawfio fio, void *dst, pawzd cap, pawju pos )
    {
    	if ( cap > 0 )
    	{
    		pawzu ps = sysconf( _SC_PAGE_SIZE );
    		pawju from = PawToLowerMultiple( pos, ps );
    		pawzu size = PawToUpperMultiple( cap, ps );
    		void *data = mmap( NULL, size, PROT_READ, MAP_SHARED, fio, from );
    		if ( !data ) return -1;
    		paw_cpy( dst, data + (pos - from), cap );
    		munmap( data, size );
    		return cap;
    	}
    	return -(cap < 0);
    }
    
    PAW_MIN_API pawzd	pawfio_write( pawfio fio, pawp src, pawzd cap )
    	{ return pawfio_writeat( fio, src, cap, pawfio_tell( fio ) ); }
    PAW_MIN_API pawzd	pawfio_fetch( pawfio fio, void *dst, pawzd cap )
    	{ return pawfio_fetchat( fio, dst, cap, pawfio_tell( fio ) ); }
    Roughly translated to pure linux code (no typedefs etc for cross platform compatability) it looks like this:

    Code:
    #define PawToLowerDivision( N, BY ) ((BY) ? (N) / (BY) : 0)
    #define PawToUpperDivision( N, BY ) ((BY) ? ((N) / (BY)) + !!((N) % (BY)) : 0)
    #define PawToLowerMultiple( N, OF ) ((OF) * PawToLowerDivision(N,OF))
    #define PawToUpperMultiple( N, OF ) ((OF) * PawToUpperDivision(N,OF))
    
    ssize_t pawfio_writeat( int fd, void const *src, ssize_t cap, uintmax_t pos )
    {
    	if ( cap > 0 )
    	{
    		size_t ps = sysconf( _SC_PAGE_SIZE );
    		uintmax_t from = PawToLowerMultiple( pos, ps );
    		size_t size = PawToUpperMultiple( cap, ps );
    		void *dest = mmap( NULL, size, PROT_WRITE, MAP_SHARED, fd, from );
    		if ( !dest ) return -1;
    		memcpy( dest + (pos - from), src, cap );
    		munmap( dest, size );
    		return cap;
    	}
    	return -(cap < 0);
    }
    
    ssize_t pawfio_fetchat( int fd, void *dst, ssize_t cap, uintmax_t pos )
    {
    	if ( cap > 0 )
    	{
    		size_t ps = sysconf( _SC_PAGE_SIZE );
    		uintmax_t from = PawToLowerMultiple( pos, ps );
    		size_t size = PawToUpperMultiple( cap, ps );
    		void *data = mmap( NULL, size, PROT_READ, MAP_SHARED, fd, from );
    		if ( !data ) return -1;
    		memcpy( dst, data + (pos - from), cap );
    		munmap( data, size );
    		return cap;
    	}
    	return -(cap < 0);
    }
    
    ssize_t pawfio_write( int fd, void const *src, ssize_t cap ) { return pawfio_writeat( fd, src, cap, lseek64( fd, 0, SEEK_CUR ) ); }
    ssize_t pawfio_fetch( int fd, void *dst, ssize_t cap ) { return pawfio_fetchat( fd, dst, cap, lseek64( fd, 0, SEEK_CUR ) ); }
    If someone's inclined please test it out while I continue with fixing up the windows code in other files that doesn't yet compile

  3. #3
    Banned
    Join Date
    Oct 2022
    Posts
    5
    One potential solution is to use the pread and pwrite system calls, which provide the same functionality as read and write, but allow for a file offset to be specified as a parameter. This way, you can avoid all the complexities associated with synchronizing file offsets, and it should be more efficient as well.

  4. #4
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Quote Originally Posted by Vithika View Post
    One potential solution is to use the pread and pwrite system calls, which provide the same functionality as read and write, but allow for a file offset to be specified as a parameter. This way, you can avoid all the complexities associated with synchronizing file offsets, and it should be more efficient as well.
    Thank you, I'll look into that as soon as I report a bug in mingw, they hid the FileSetPointer & FileSetPointerEx behind this:
    Code:
    #if WINAPI_FAMILY_PARTITION (WINAPI_PARTITION_DESKTOP) || _WIN32_WINNT >= _WIN32_WINNT_WIN10
    The 1st condition is fine but the 2nd is flat out wrong, that function was available way earlier than Windows 10 and I've not been able to compile as a result of it

  5. #5
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    FYI: "||" means or
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  6. #6
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Quote Originally Posted by stahta01 View Post
    FYI: "||" means or
    I know, that's why I said the FIRST CONDITION is fine, I tried setting the WINAPI_FAMILY define directly to trigger a "true" result there but that just resulted in nothing being defined, no DWORD, no CreateFile, no nothing, something is abysmally wrong for that to happen

  7. #7
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Quote Originally Posted by awsdert View Post
    Thank you, I'll look into that as soon as I report a bug in mingw, they hid the FileSetPointer & FileSetPointerEx behind this:
    Code:
    #if WINAPI_FAMILY_PARTITION (WINAPI_PARTITION_DESKTOP) || _WIN32_WINNT >= _WIN32_WINNT_WIN10
    The 1st condition is fine but the 2nd is flat out wrong, that function was available way earlier than Windows 10 and I've not been able to compile as a result of it
    I'm a dumbass, I remembered the function names wrong, was supposed to use SetFilePointer instead of FileSetPointer,

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 3
    Last Post: 01-09-2016, 04:21 PM
  2. Replies: 2
    Last Post: 03-30-2013, 02:50 AM
  3. Looking for info: Cross-Platform
    By AvidGamer in forum C++ Programming
    Replies: 7
    Last Post: 09-13-2010, 10:19 AM
  4. Cross-Platform GUI
    By @nthony in forum C++ Programming
    Replies: 4
    Last Post: 10-24-2007, 02:51 PM
  5. Cross-platform code...
    By Sul in forum C++ Programming
    Replies: 10
    Last Post: 06-18-2004, 04:44 PM

Tags for this Thread