## 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.pkgstipulate
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 package 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_full_maildrop ();
fun with_lock f x
=
{
md::take_from_maildrop lock_maildrop;
#
f x
then
md::put_in_maildrop (lock_maildrop, ());
}
except
ex = {
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
#
(\\ 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' ==> (\\ _ = md1::put_in_oneshot (reply_1shot, ())),
nack
];
};
md1::get_from_oneshot' reply_1shot
==>
(\\ _ = f x);
};
THE _ => file_read_now_possible'
==>
(\\ _ = {
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 package 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::take_from_maildrop lock_drop;
f x
then
md::put_in_maildrop (lock_drop, ());
}
except
x = {
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
#
(\\ 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' ==> (\\ _ = md1::put_in_oneshot (reply_drop, ())),
nack
];
};
md1::get_from_oneshot' reply_drop
==>
(\\ _ = f x);
};
THE _ => file_write_now_possible'
==>
(\\ _ = {
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;