for review: file locking

Thomas Charles CONWAY conway at cs.mu.oz.au
Tue Jul 15 14:48:48 AEST 1997


Hi

For whoever.

-- 
ZZ:wq!
^X^C
Thomas Conway               				      conway at cs.mu.oz.au
AD DEUM ET VINUM	  			      Every sword has two edges.


library/io.m:
	add io__lock_file and io__unlock_file which perform
	advisory locking on (open) files.

NEWS:
	mention io__lock_file and io__unlock_file.

cvs diff: Diffing .
Index: NEWS
===================================================================
RCS file: /home/staff/zs/imp/mercury/NEWS,v
retrieving revision 1.58
diff -u -r1.58 NEWS
--- NEWS	1997/07/08 16:48:05	1.58
+++ NEWS	1997/07/15 04:46:20
@@ -191,8 +191,11 @@
     lists using a user-specified procedure to write the elements and separating
     the elements with a user-specified separator string.
 
-  - We've add io__read_file/{3,4} and io__read_binary_file/{3,4} which read
+  - We've added io__read_file/{3,4} and io__read_binary_file/{3,4} which read
     whole files (until error or eof).
+
+  - We've added io__lock_file and io__unlock_file which perform advisory
+    file locking with the POSIX flock call.
 
   - We've added a double accumulator version of list__foldl/4 called
     list__foldl2/6, which is a convenient generalisation for accumulators
cvs diff: Diffing bindist
cvs diff: Diffing boehm_gc
cvs diff: Diffing boehm_gc/Mac_files
cvs diff: Diffing boehm_gc/cord
cvs diff: Diffing boehm_gc/cord/private
cvs diff: Diffing boehm_gc/include
cvs diff: Diffing boehm_gc/include/private
cvs diff: Diffing bytecode
cvs diff: Diffing compiler
cvs diff: Diffing compiler/notes
cvs diff: Diffing doc
cvs diff: Diffing extras
cvs diff: Diffing extras/cgi
cvs diff: Diffing extras/complex_numbers
cvs diff: Diffing extras/complex_numbers/samples
cvs diff: Diffing extras/complex_numbers/tests
cvs diff: Diffing library
Index: library/io.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/library/io.m,v
retrieving revision 1.126
diff -u -r1.126 io.m
--- io.m	1997/06/30 06:35:39	1.126
+++ io.m	1997/07/15 04:43:20
@@ -21,7 +21,7 @@
 
 :- module io.
 :- interface.
-:- import_module char, string, std_util, list.
+:- import_module bool, char, string, std_util, list.
 
 %-----------------------------------------------------------------------------%
 
@@ -838,6 +838,41 @@
 
 %-----------------------------------------------------------------------------%
 
+% File locking predicates (using adivsory locking only)
+
+:- type lock_type
+	--->	shared
+	;	exclusive
+	.
+
+:- type block
+	--->	block
+	;	no_block
+	.
+
+:- type io__poly_stream
+	--->	i(io__input_stream)
+	;	o(io__output_stream)
+	;	bi(io__binary_input_stream)
+	;	bo(io__binary_output_stream)
+	.
+
+	% Attempt to obtain a lock on a file.
+	% A file may have multiple shared locks, but only one exclusive
+	% lock. A file may not have both a shared lock and an exclusive
+	% lock simultaneously. If the block parameter is set to `block'
+	% then execution will block until the requested lock becomes
+	% available.
+:- pred io__lock_file(io__poly_stream, lock_type, block, io__res(bool),
+		io__state, io__state).
+:- mode io__lock_file(in, in, in, out, di, uo) is det.
+
+	% Unlock a file.
+:- pred io__unlock_file(io__poly_stream, io__state, io__state).
+:- mode io__unlock_file(in, di, uo) is det.
+
+%-----------------------------------------------------------------------------%
+
 % Memory management predicates.
 
 	% Write some memory/time usage statistics to stdout.
@@ -2698,8 +2733,8 @@
 
 /*---------------------------------------------------------------------------*/
 
-io__remove_file(FileName, Result, IO, IO) :-
-	io__remove_file_2(FileName, Res, ResString),
+io__remove_file(FileName, Result, IO0, IO) :-
+	io__remove_file_2(FileName, Res, ResString, IO0, IO),
 	( Res < 0 ->
 		Result = error(ResString)
 	;
@@ -2707,13 +2742,14 @@
 	).
 
 
-:- pred io__remove_file_2(string, int, string).
-:- mode io__remove_file_2(in, out, out) is det.
+:- pred io__remove_file_2(string, int, string, io__state, io__state).
+:- mode io__remove_file_2(in, out, out, di, uo) is det.
 
 %#include <string.h>
 %#include <errno.h>
 %#include "prof.h" % for strerror
-:- pragma(c_code, io__remove_file_2(FileName::in, RetVal::out, RetStr::out), "{
+:- pragma(c_code, io__remove_file_2(FileName::in, RetVal::out, RetStr::out,
+		IO0::di, IO::uo), "{
 	Word tmp;
 	char *buf;
 
@@ -2727,7 +2763,105 @@
 	} else {
 		RetStr = NULL;
 	}
+	update_io(IO0, IO);
 }").
 
+%------------------------------------------------------------------------------%
+
+:- pragma c_header_code("
+	#include <sys/file.h>
+").
+
+io__lock_file(PolyStream, Lock, Block, Result) -->
+	{ lock_type_to_flag(Lock, LockFlag) },
+	{ block_to_flag(Block, BlockFlag) },
+	{ unwrap_poly_stream(PolyStream, Stream) },
+	io__lock_file_2(Stream, LockFlag \/ BlockFlag, Status, Errno),
+	(
+		{ Status = 0 }
+	->
+		{ Result = ok(yes) }
+	;
+		{ would_block(Errno) }
+	->
+		{ Result = ok(no) }
+	;
+		{ Result = error("locking error") }
+	).
+
+:- pred io__lock_file_2(io__stream, int, int, int, io__state, io__state).
+:- mode io__lock_file_2(in, in, out, out, di, uo) is det.
+
+:- pragma c_code(io__lock_file_2(Stream::in, Flags::in, RStat::out,
+		Errno::out, IO0::di, IO::uo), "{
+
+	MercuryFile *stream = (MercuryFile *) Stream;
+
+	RStat = flock(fileno(stream->file), Flags);
+	Errno = errno;
+
+	update_io(IO0, IO);
+}").
+
+:- pred unwrap_poly_stream(io__poly_stream, io__stream).
+:- mode unwrap_poly_stream(in, out) is det.
+
+unwrap_poly_stream(i(S), S).
+unwrap_poly_stream(o(S), S).
+unwrap_poly_stream(bi(S), S).
+unwrap_poly_stream(bo(S), S).
+
+:- pred lock_type_to_flag(lock_type, int).
+:- mode lock_type_to_flag(in, out) is det.
+
+lock_type_to_flag(shared, Shared) :-
+	lock_type_to_flag_2(0, Shared).
+lock_type_to_flag(exclusive, Exclusive) :-
+	lock_type_to_flag_2(1, Exclusive).
+
+:- pred lock_type_to_flag_2(int, int).
+:- mode lock_type_to_flag_2(in, out) is det.
+
+:- pragma c_code(lock_type_to_flag_2(I::in, F::out), "{
+	static int lock_flags[] = { LOCK_SH, LOCK_EX };
+	F = lock_flags[I];
+}").
+
+:- pred block_to_flag(block, int).
+:- mode block_to_flag(in, out) is det.
+
+block_to_flag(block, 0).
+block_to_flag(no_block, Block) :-
+	block_to_flag_2(Block).
+
+:- pred block_to_flag_2(int).
+:- mode block_to_flag_2(out) is det.
+
+:- pragma c_code(block_to_flag_2(F::out), "{
+	F = LOCK_NB;
+}").
+
+:- pred would_block(int::out) is det.
+
+:- pragma c_code(would_block(I::out), "I = EWOULDBLOCK;").
+
+%------------------------------------------------------------------------------%
+
+io__unlock_file(PolyStream) -->
+	{ unwrap_poly_stream(PolyStream, Stream) },
+	io__unlock_file_2(Stream).
+
+:- pred io__unlock_file_2(io__stream, io__state, io__state).
+:- mode io__unlock_file_2(in, di, uo) is det.
+
+:- pragma c_code(io__unlock_file_2(Stream::in, IO0::di, IO::uo), "{
+
+	MercuryFile *stream = (MercuryFile *) Stream;
+
+	flock(fileno(stream->file), LOCK_UN);
+
+	update_io(IO0, IO);
+}").
+
+%------------------------------------------------------------------------------%
 
-/*---------------------------------------------------------------------------*/
Index: library/string.nu.nl
===================================================================
RCS file: /home/staff/zs/imp/mercury/library/string.nu.nl,v
retrieving revision 1.15
diff -u -r1.15 string.nu.nl
--- string.nu.nl	1997/07/14 03:38:15	1.15
+++ string.nu.nl	1997/07/14 22:01:39
@@ -84,3 +84,8 @@
 	list__member(CharCode, List).
 
 %-----------------------------------------------------------------------------%
+
+string__unsafe_index(String, Index, Char) :-
+	string__index(String, Index, Char).
+
+%-----------------------------------------------------------------------------%
cvs diff: Diffing lp_solve
cvs diff: Diffing lp_solve/lp_examples
cvs diff: Diffing profiler
cvs diff: Diffing runtime
cvs diff: Diffing runtime/machdeps
cvs diff: Diffing samples
cvs diff: Diffing samples/c_interface
cvs diff: Diffing samples/c_interface/c_calls_mercury
cvs diff: Diffing samples/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/c_interface/mercury_calls_c
cvs diff: Diffing samples/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/diff
cvs diff: Diffing scripts
cvs diff: Diffing tools
cvs diff: Diffing trial
cvs diff: Diffing util



More information about the developers mailing list