PreviousUpNext

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

## winix-data-file-io-driver-for-posix.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--premicrothread.pkg).

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

# See also:
#     src/lib/src/lib/thread-kit/src/win32/winix-data-file-io-driver-for-win32.pkg




stipulate
    package dio =  winix_base_data_file_io_driver_for_posix;                    # winix_base_data_file_io_driver_for_posix              is from   src/lib/std/src/io/winix-base-data-file-io-driver-for-posix.pkg
    package iom =  io_now_possible_mailop;                                      # io_now_possible_mailop                                is from   src/lib/src/lib/thread-kit/src/core-thread-kit/io-now-possible-mailop.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  =  posixlib;                                                    # posixlib                                              is from   src/lib/std/src/psx/posixlib.pkg
    package pio =  posixlib;
herein

    # We get compiletime passed as a generic arg in:
    #
    #     src/lib/std/src/posix/data-file.pkg
    #
    package winix_data_file_io_driver_for_posix
    #
    : (weak)  Winix_Extended_File_Io_Driver_For_Os                              # Winix_Extended_File_Io_Driver_For_Os                  is from   src/lib/std/src/io/winix-extended-file-io-driver-for-os.api
    {
        package drv = winix_base_data_file_io_driver_for_posix;                 # winix_base_data_file_io_driver_for_posix              is from   src/lib/std/src/io/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_plain_file fd
            =
            pf::stat::is_file  (pf::fstat  fd);

        fun pos_fns (closed, fd)
            =
            if (is_plain_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_maildrop =  md::make_maildrop ();

                fun with_lock f x
                    =
                    {
log::note_in_ramlog .{ sprintf "make_filereader/with_lock calling empty  *uninterruptible_scope_mutex d=%d"   *microthread_preemptive_scheduler::uninterruptible_scope_mutex; };
                        md::take_from_maildrop  lock_maildrop;
                        #
                        f x
                        before
{
log::note_in_ramlog .{ sprintf "make_filereader/with_lock calling fill  *uninterruptible_scope_mutex d=%d"   *microthread_preemptive_scheduler::uninterruptible_scope_mutex; };
                            md::put_in_maildrop (lock_maildrop, ());
};
                    }
                    except
                        ex = {
log::note_in_ramlog .{ sprintf "make_filereader/with_lock II calling fill  *uninterruptible_scope_mutex d=%d"   *microthread_preemptive_scheduler::uninterruptible_scope_mutex; };
                                md::put_in_maildrop (lock_maildrop, ());
                                raise exception ex;
                             };

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


                closed = REF FALSE;

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

                fun inc_pos k                                                           # "inc_pos" == "increment [file] position".
                    =
                    pos :=  pos::(+)  (*pos, to_fpi k);

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

                file_read_now_possible'
                    =
                    iom::io_now_possible_on'  { io_descriptor,  readable => TRUE,  writable => FALSE,  oobdable => FALSE };

                fun mailop_wrap f x
                    =
                    dynamic_mailop_with_nack
                        #
                        (fn nack
                            =
                            {   if *closed   raise exception iox::CLOSED_IO_STREAM;  fi;
                                #
                                case (md::nonblocking_take_from_maildrop  lock_maildrop)
                                    #
                                    NULL =>     {   reply_1shot =  md1::make_oneshot_maildrop ();
                                                    #
                                                    make_thread "binary primitive I/O"
                                                       .{   do_one_mailop [
                                                                file_read_now_possible'  ==>  (fn _ = md1::put_in_oneshot (reply_1shot, ())),
                                                                nack
                                                            ];
                                                        };

                                                    md1::take_from_oneshot'  reply_1shot
                                                        ==>
                                                        (fn _ = f x);
                                                };

                                    THE _ =>    file_read_now_possible'
                                                    ==>
                                                    (fn _ = {
log::note_in_ramlog .{ sprintf "mailop_wrapp calling fill  *uninterruptible_scope_mutex d=%d   -- threadkit-winix-data-file-io-driver-for-posix"   *microthread_preemptive_scheduler::uninterruptible_scope_mutex; };
                                                                md::put_in_maildrop (lock_maildrop, ());
                                                                f x;
                                                            }
                                                    );
                                esac;
                            }
                        );

                fun read_vector n
                    =
                    {   block_until_mailop_fires  file_read_now_possible';
                        #
                        v =  pio::read_as_vector  { file_descriptor => fd,  max_bytes_to_read => n };

                        inc_pos (vec::length v);

                        v;
                    };

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

                is_plain =  is_plain_file  fd;

                fun avail ()
                    =
                    if *closed
                        #
                        THE 0;
                    else
                        is_plain  ??  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_vector_mailop    =>  mailop_wrap  read_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_maildrop ();

                fun with_lock f x
                    =
                    {
log::note_in_ramlog .{ sprintf "make_filewriter/with_lock calling empty  *uninterruptible_scope_mutex d=%d"   *microthread_preemptive_scheduler::uninterruptible_scope_mutex; };
                        md::take_from_maildrop lock_drop;

                        f x
                        before
{
log::note_in_ramlog .{ sprintf "make_filewriter/with_lock calling fill  *uninterruptible_scope_mutex d=%d"   *microthread_preemptive_scheduler::uninterruptible_scope_mutex; };
                            md::put_in_maildrop (lock_drop, ());
};
                    }
                    except
                        x = {
log::note_in_ramlog .{ sprintf "make_filewriter/with_lock II calling fill  *uninterruptible_scope_mutex d=%d"   *microthread_preemptive_scheduler::uninterruptible_scope_mutex; };
                                md::put_in_maildrop (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_vector x = pio::write_vector    x;
                fun put_rw_vector x = pio::write_rw_vector x;

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

                file_write_now_possible'
                    =
                    iom::io_now_possible_on'
                      {
                        io_descriptor,
                        readable =>  FALSE,
                        writable =>  TRUE,
                        oobdable =>  FALSE
                      };

                fun mailop_wrap f x
                    =
                    dynamic_mailop_with_nack
                        #
                        (fn nack =  {   if *closed   raise exception  iox::CLOSED_IO_STREAM;   fi;
                                        #
                                        case (md::nonblocking_take_from_maildrop lock_drop)
                                            #
                                            NULL =>     {   reply_drop =  md1::make_oneshot_maildrop ();
                                                            #
                                                            make_thread "binary primitive I/O II"
                                                               .{   do_one_mailop [
                                                                        #
                                                                        file_write_now_possible'  ==>  (fn _ = md1::put_in_oneshot (reply_drop, ())),
                                                                        nack
                                                                    ];
                                                                };

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

                                            THE _ =>    file_write_now_possible'
                                                            ==>
                                                            (fn _ =  {
log::note_in_ramlog .{ sprintf "mailop_wrap calling fill  *uninterruptible_scope_mutex d=%d"   *microthread_preemptive_scheduler::uninterruptible_scope_mutex; };
                                                                        md::put_in_maildrop (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_vector),
                    write_rw_vector         =>  with_lock (write put_rw_vector),
                    #
                    write_vector_mailop     =>  mailop_wrap (write put_vector),
                    write_rw_vector_mailop  =>  mailop_wrap (write put_rw_vector),
                    #
                    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