


## 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.pkgstipulate
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.pkgherein
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;


