PreviousUpNext

15.4.1137  src/lib/std/src/posix/threadkit-winix-data-file-io-driver-for-posix.pkg

## threadkit-winix-data-file-io-driver-for-posix.pkg

# Compiled by:
#     src/lib/std/standard.lib

# This may be redundant with
#     src/lib/src/lib/thread-kit/src/win32/threadkit-winix-data-file-io-driver-for-win32.pkg


# This implements the UNIX version of the OS specific binary primitive
# IO package.  The Text IO version is implemented by a trivial translation
# of these operations (see winix-text-file-io-driver-for-posix.pkg).

# We get compiletime passed as a generic arg in:
#     src/lib/std/src/posix/threadkit-data-file.pkg

stipulate
    package dio =  threadkit_winix_base_data_file_io_driver_for_posix;          # threadkit_winix_base_data_file_io_driver_for_posix    is from   src/lib/std/src/io/threadkit-winix-base-data-file-io-driver-for-posix.pkg
    package io  =  threadkit_io_manager;                                        # threadkit_io_manager                                  is from   src/lib/src/lib/thread-kit/src/core-thread-kit/threadkit-io-manager.pkg
    package iox =  io_exceptions;                                               # io_exceptions                                         is from   src/lib/std/src/io/io-exceptions.pkg
    package md  =  maildrop;                                                    # maildrop                                              is from   src/lib/src/lib/thread-kit/src/core-thread-kit/maildrop.pkg
    package md1 =  oneshot_maildrop;                                            # oneshot_maildrop                                      is from   src/lib/src/lib/thread-kit/src/core-thread-kit/oneshot-maildrop.pkg
    package pos =  file_position;                                               # file_position                                         is from   src/lib/std/file-position.pkg
    #
    package vec =  vector_of_one_byte_unts;                                     # vector_of_one_byte_unts                               is from   src/lib/std/src/vector-of-one-byte-unts.pkg
    package pf  =  posix_1003_1b;                                               # posix_1003_1b                                         is from   src/lib/std/src/posix-1003.1b/posix-1003-1b.pkg
    package pio =  posix_1003_1b;
    package rse =  retry_syscall_on_eintr;                                      # retry_syscall_on_eintr                                is from   src/lib/std/src/threadkit/posix/retry-syscall-on-eintr.pkg
herein

    package threadkit_winix_data_file_io_driver_for_posix
    #
    : (weak)  Threadkit_Winix_Extended_File_Io_Driver_For_Os                    # Threadkit_Winix_Extended_File_Io_Driver_For_Os        is from   src/lib/std/src/io/threadkit-winix-extended-file-io-driver-for-os.api
    {
        package drv = threadkit_winix_base_data_file_io_driver_for_posix;       # threadkit_winix_base_data_file_io_driver_for_posix    is from   src/lib/std/src/io/threadkit-winix-base-data-file-io-driver-for-posix.pkg
                                                                                # drv is exported to clients.

        File_Descriptor = pf::File_Descriptor;

        to_fpi = pos::from_int;

        best_io_quantum = 4096;                                                 # Reading and writing 4KB at a time should be reasonably efficient.

        fun is_reg_file fd
            =
            pf::stat::is_file (pf::fstat fd);

        fun pos_fns (closed, fd)
            =
            if (is_reg_file fd)

                pos = REF (pos::from_int 0);

                fun get_file_position ()
                    =
                    *pos;

                fun set_file_position p
                    =
                    {   if *closed
                            raise exception iox::CLOSED_IO_STREAM;
                        fi;

                        pos := pio::lseek (fd, p, pio::SEEK_SET);
                    };

                fun end_file_position ()
                    =
                    {   if *closed
                            raise exception iox::CLOSED_IO_STREAM;
                        fi;
                        pf::stat::size (pf::fstat fd);
                    };

                fun verify_file_position ()
                    =
                    {   cur_pos =  pio::lseek (fd, pos::from_int 0, pio::SEEK_CUR);

                        pos := cur_pos;

                        cur_pos;
                    };

                ignore (verify_file_position());

                { pos,
                  get_file_position    =>  THE get_file_position,
                  set_file_position    =>  THE set_file_position,
                  end_file_position    =>  THE end_file_position,
                  verify_file_position =>  THE verify_file_position
                };

            else 
                { pos             =>  REF (pos::from_int 0),
                  get_file_position    =>  NULL,
                  set_file_position    =>  NULL,
                  end_file_position    =>  NULL,
                  verify_file_position =>  NULL
                };
            fi;

        fun make_filereader { fd, filename }
            =
            {   include threadkit;                                                      # threadkit             is from   src/lib/src/lib/thread-kit/src/core-thread-kit/threadkit.pkg

                io_descriptor =  pf::fd_to_iod  fd;

                lock_mv =  md::make_full_maildrop ();

                fun with_lock f x
                    =
                    {   md::empty  lock_mv;

                        (rse::do_syscall_retry_on_eintr f x)
                        before
                            md::fill (lock_mv, ());
                    }
                    except
                        ex = {   md::fill (lock_mv, ());
                                 raise exception ex;
                             };

                fun with_lock' (THE f)
                        =>
                        THE (with_lock f);

                    with_lock' NULL
                        =>
                        NULL;
                end;


                closed = REF FALSE;

                my { pos, get_file_position, set_file_position, end_file_position, verify_file_position }
                    =
                    pos_fns (closed, fd);

                fun inc_pos k
                    =
                    pos := pos::(+) (*pos, to_fpi k);

                fun block_wrap f x
                    =
                    {   if *closed
                            raise exception iox::CLOSED_IO_STREAM;
                        fi;

                        f x;
                    };

                read_mailop
                    =
                    io::io_mailop { io_descriptor, readable => TRUE, writable => FALSE, oobdable => FALSE };

                fun mailop_wrap f x
                    =
                    with_nack
                        (fn nack
                            =
                            {   if *closed
                                    raise exception iox::CLOSED_IO_STREAM;
                                fi;

                                case (md::nonblocking_empty  lock_mv)

                                    NULL =>
                                        {   repl_v = md1::make_oneshot_maildrop ();

                                            make_thread "binary primitive I/O"
                                               .{   select [
                                                        read_mailop  ==>  (fn _ = md1::set (repl_v, ())),
                                                        nack
                                                    ];
                                                };

                                            md1::get'  repl_v
                                                ==>
                                                (fn _ = f x);
                                        };

                                    THE _
                                        =>
                                        read_mailop
                                            ==>
                                            (fn _ = {   md::fill (lock_mv, ());
                                                        f x;
                                                    }
                                            );
                                esac;
                            }
                        );

                fun read_vector n
                    =
                    {   do_mailop  read_mailop;
                        #
                        v =  pio::read_as_vector  { file_descriptor => fd,  max_bytes_to_read => n };

                        inc_pos (vec::length v);

                        v;
                    };

                fun read_rw_vector  buffer
                    =
                    {   do_mailop  read_mailop;
                        #
                        k = pio::read_into_buffer  {  file_descriptor => fd,  buffer  };

                        inc_pos k;

                        k;
                    };

                fun close ()
                    =
                    if (not *closed)
                        #
                        closed := TRUE;
                        pio::close  fd;
                    fi;

                is_reg =  is_reg_file  fd;

                fun avail ()
                    =
                    if *closed
                        #
                        THE 0;
                    else
                        is_reg  ??  THE (pos::to_int  (pf::stat::size  (pf::fstat fd) - *pos))
                                ::  NULL;
                    fi;

                dio::FILEREADER
                  {
                    filename,
                    io_descriptor         =>  THE io_descriptor,
                    #
                    read_vector           =>  with_lock  (block_wrap read_vector),
                    #
                    read_rw_vector        =>  with_lock  (block_wrap read_rw_vector),
                    read_vector_mailop    =>  mailop_wrap  read_vector,
                    read_rw_vector_mailop =>  mailop_wrap  read_rw_vector,
                    #
                    avail                 =>  with_lock  avail,
                    #
                    get_file_position     =>  with_lock'  get_file_position,
                    set_file_position     =>  with_lock'  set_file_position,
                    #
                    end_file_position     =>  with_lock'  end_file_position,
                    verify_file_position  =>  with_lock'  verify_file_position,
                    #
                    close                 =>  with_lock  close,
                    best_io_quantum
                  };
              };


        fun open_for_read  filename
            =
            make_filereader
              {
                filename,
                fd => pf::openf  (filename,  pf::O_RDONLY,  pf::o::flags [])
              };


        fun make_filewriter { fd, filename, append_mode, best_io_quantum }
            =
            {   include threadkit;                                                      # threadkit             is from   src/lib/src/lib/thread-kit/src/core-thread-kit/threadkit.pkg
                #
                io_descriptor =  pf::fd_to_iod  fd;

                lock_drop = md::make_full_maildrop ();

                fun with_lock f x
                    =
                    {   md::empty lock_drop;

                        (rse::do_syscall_retry_on_eintr f x)
                        before
                            md::fill (lock_drop, ());
                    }
                    except
                        x = {   md::fill (lock_drop, ());
                                #
                                raise exception x;
                            };

                fun with_lock' (THE f) =>  THE (with_lock f);
                    with_lock' NULL    =>  NULL;
                end;

                closed = REF FALSE;

                append_fs
                    =
                    pio::flags::flags
                        if append_mode  [pio::flags::append];
                        else            [];
                        fi;

                fun update_status ()
                    =
                    pio::setfl (fd, append_fs);

                fun ensure_open ()
                    =
                    if *closed   raise exception iox::CLOSED_IO_STREAM;   fi;

                fun put_v x = pio::write_vector    x;                           # This should be renamed to put_vector          XXX SUCKO FIXME
                fun put_a x = pio::write_rw_vector x;                           # This should be renamed to put_rw_vector       XXX SUCKO FIXME

                fun write put arg
                    =
                    {   ensure_open ();
                        put (fd, arg);
                    };

                write_mailop
                    =
                    io::io_mailop { io_descriptor,  readable =>  FALSE,
                                                    writable =>  TRUE,
                                                    oobdable =>  FALSE
                                  };

                fun mailop_wrap f x
                    =
                    with_nack
                        (fn nack =  {   if *closed
                                            raise exception  iox::CLOSED_IO_STREAM;
                                        fi;

                                        case (md::nonblocking_empty lock_drop)

                                            NULL =>
                                                {   reply_drop = md1::make_oneshot_maildrop ();

                                                    make_thread "binary primitive I/O II"
                                                       .{   select
                                                              [ write_mailop  ==>  (fn _ = md1::set (reply_drop, ())),
                                                                nack
                                                              ];
                                                        };

                                                    md1::get' reply_drop
                                                        ==>
                                                        (fn _ =  f x);
                                                };

                                            THE _
                                                =>
                                                write_mailop
                                                    ==>
                                                    (fn _ =  {   md::fill (lock_drop, ());
                                                                 f x;
                                                             }
                                                    );
                                        esac;
                                    }
                        );

                fun close ()
                    =
                    if (not *closed)
                        closed := TRUE;
                        pio::close fd;
                    fi;

                (pos_fns (closed, fd))
                    ->
                    { pos, get_file_position, set_file_position, end_file_position, verify_file_position };

                dio::FILEWRITER
                  {
                    filename,
                    best_io_quantum         =>  best_io_quantum,
                    #
                    write_vector            =>  with_lock (write put_v),
                    write_rw_vector         =>  with_lock (write put_a),
                    #
                    write_vector_mailop     =>  mailop_wrap (write put_v),
                    write_rw_vector_mailop  =>  mailop_wrap (write put_a),
                    #
                    get_file_position       =>  with_lock' get_file_position,
                    set_file_position       =>  with_lock' set_file_position,
                    #
                    end_file_position       =>  with_lock' end_file_position,
                    verify_file_position    =>  with_lock' verify_file_position,
                    #
                    close                   =>  with_lock close,
                    io_descriptor           =>  THE io_descriptor
                  };
            };

        standard_mode           #  mode 0666 
            =
            pf::s::flags
              [
                pf::s::irusr, pf::s::iwusr,
                pf::s::irgrp, pf::s::iwgrp,
                pf::s::iroth, pf::s::iwoth
              ];

        fun create_file (filename, mode, flags)                 # "In order to make an apple pie from scratch, you must first create the universe."   -- Carl Sagan
            =
            pf::createf (filename, mode, flags, standard_mode);

        fun open_for_write  filename
            =
            make_filewriter
              {
                filename,
                fd          => create_file (filename, pf::O_WRONLY, pf::o::trunc),
                append_mode => FALSE,
                best_io_quantum
              };

        fun open_for_append  filename
            =
            make_filewriter
              {
                filename,
                fd              =>  create_file (filename, pf::O_WRONLY, pf::o::append),
                append_mode     =>  TRUE,
                best_io_quantum
              };

    };                                          # package winix_data_file_io_driver_for_posix 

end;


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext