20 #include "SheafSystem/read_write_monitor.h" 21 #include "SheafSystem/assert_contract.h" 22 #include "SheafSystem/std_cstdlib.h" 23 #include "SheafSystem/std_iostream.h" 49 int rtncode = pthread_mutex_init(&read_write_monitor_mutex,0);
52 rtncode = pthread_cond_init(&lock_free,0);
59 rtncode = pthread_mutex_lock(&read_write_monitor_mutex);
70 initialize_thread_state();
79 rtncode = pthread_mutex_unlock(&read_write_monitor_mutex);
123 return private_access_control_disabled();
158 private_access_control_disabled() =
false;
175 sheaf::read_write_monitor::
176 private_access_control_disabled()
185 static bool result =
true;
352 pthread_mutex_lock(&read_write_monitor_mutex);
355 result = abs(access_mode());
359 pthread_mutex_unlock(&read_write_monitor_mutex);
376 if(uncontrolled_is_read_write_accessible())
382 request_read_write_access();
390 request_read_only_access();
418 if(xrelease_read_only_access && uncontrolled_is_read_only_accessible())
427 switch_depth() = old_access_request_depth;
431 while(uncontrolled_is_read_only_accessible())
433 release_read_only_access();
440 request_read_write_access();
443 assertion(uncontrolled_is_read_write_accessible() &&
449 request_read_write_access();
472 if(uncontrolled_is_read_write_accessible())
479 release_read_write_access();
481 while(xall && uncontrolled_is_read_write_accessible());
489 while(uncontrolled_is_read_write_accessible())
491 release_read_write_access();
496 request_read_only_access();
499 assertion(uncontrolled_is_read_only_accessible() && (
access_request_depth() == switch_depth()));
504 else if(uncontrolled_is_read_only_accessible())
511 release_read_only_access();
513 while(xall && uncontrolled_is_read_only_accessible());
542 return _access_guards_disabled;
549 _access_guards_disabled =
true;
558 _access_guards_disabled =
false;
601 sheaf::read_write_monitor::
602 uncontrolled_is_read_write_accessible()
const 610 pthread_mutex_lock(&read_write_monitor_mutex);
613 result = (access_mode() > 0);
617 pthread_mutex_unlock(&read_write_monitor_mutex);
667 sheaf::read_write_monitor::
668 uncontrolled_is_read_only_accessible()
const 678 pthread_mutex_lock(&read_write_monitor_mutex);
681 result = (access_mode() < 0);
685 pthread_mutex_unlock(&read_write_monitor_mutex);
700 sheaf::read_write_monitor::
701 initialize_thread_state()
707 require(!contains_thread_state());
713 thread_state_t new_thread_state = {0,
false};
717 unordered_map<pthread_t, thread_state_t>::value_type lval(pthread_self(), new_thread_state);
718 _thread_state.insert(lval);
722 ensure(contains_thread_state());
735 _thread_state._access_mode = 0;
736 _thread_state._switch_depth = 0;
737 _thread_state._is_modified =
false;
741 ensure(contains_thread_state());
748 sheaf::read_write_monitor::
749 contains_thread_state()
const 762 result = (_thread_state.find(pthread_self()) != _thread_state.end());
781 sheaf::read_write_monitor::thread_state_t&
782 sheaf::read_write_monitor::
787 require(contains_thread_state());
793 return *_thread_state.find(pthread_self());
797 return _thread_state;
804 sheaf::read_write_monitor::
809 require(contains_thread_state());
818 return thread_state()._access_mode;
823 sheaf::read_write_monitor::
828 require(contains_thread_state());
837 return thread_state()._switch_depth;
841 sheaf::read_write_monitor::
842 request_read_only_access()
const 846 pthread_mutex_lock(&read_write_monitor_mutex);
851 require( access_mode() <= 0 );
861 pthread_cond_wait(&lock_free, &read_write_monitor_mutex);
868 int& state = access_mode();
898 pthread_mutex_unlock(&read_write_monitor_mutex);
907 sheaf::read_write_monitor::
908 request_read_write_access()
const 912 pthread_mutex_lock(&read_write_monitor_mutex);
917 require(access_mode() >= 0);
921 int& state = access_mode();
938 while( _ro_ct > 0 || _rw_ct > 0)
940 pthread_cond_wait(&lock_free, &read_write_monitor_mutex);
958 ensure(access_mode() > 0);
962 pthread_mutex_unlock(&read_write_monitor_mutex);
970 sheaf::read_write_monitor::
971 release_read_only_access()
const 976 pthread_mutex_lock(&read_write_monitor_mutex);
982 require( access_mode() < 0 );
988 int& state = access_mode();
996 define_old_variable(
int old_ro_ct = _ro_ct);
1014 pthread_cond_signal(&lock_free);
1022 ensure((_ro_ct == old_ro_ct) || (_ro_ct == old_ro_ct - 1));
1026 pthread_mutex_unlock(&read_write_monitor_mutex);
1034 sheaf::read_write_monitor::
1035 release_read_write_access()
const 1039 pthread_mutex_lock(&read_write_monitor_mutex);
1044 require( access_mode() > 0 );
1050 int& state = access_mode();
1058 define_old_variable(
int old_rw_ct = _rw_ct);
1071 unordered_map<pthread_t, thread_state_t>::iterator itr = _thread_state.begin();
1073 while(itr != _thread_state.end())
1075 itr->second._is_modified =
true;
1083 pthread_cond_broadcast(&lock_free);
1089 _thread_state._is_modified =
true;
1098 ensure((_rw_ct == old_rw_ct) || (_rw_ct == old_rw_ct - 1));
1099 ensure(unexecutable(
"for all client threads: is_modified()"));
1103 pthread_mutex_unlock(&read_write_monitor_mutex);
1128 pthread_mutex_lock(&read_write_monitor_mutex);
1131 result = thread_state()._is_modified;
1135 pthread_mutex_unlock(&read_write_monitor_mutex);
1153 pthread_mutex_lock(&read_write_monitor_mutex);
1156 thread_state()._is_modified =
false;
1160 pthread_mutex_unlock(&read_write_monitor_mutex);
1186 pthread_mutex_lock(&read_write_monitor_mutex);
1193 pthread_mutex_unlock(&read_write_monitor_mutex);
1214 pthread_mutex_lock(&read_write_monitor_mutex);
1217 result = _mode_lock_ct;
1221 pthread_mutex_unlock(&read_write_monitor_mutex);
1236 pthread_mutex_lock(&read_write_monitor_mutex);
1247 require( access_mode() != 0 );
1258 pthread_cond_wait(&lock_free, &read_write_monitor_mutex);
1265 define_old_variable(
int old_mode_lock_ct = _mode_lock_ct);
1274 ensure(_mode_lock_ct == old_mode_lock_ct + 1);
1275 ensure(_mode_lock_ct > 0);
1279 ensure(_rw_ct == 0);
1280 pthread_mutex_unlock(&read_write_monitor_mutex);
1296 pthread_mutex_lock(&read_write_monitor_mutex);
1302 require( _mode_lock_ct > 0 );
1309 define_old_variable(
int old_mode_lock_ct = _mode_lock_ct);
1325 pthread_cond_signal(&lock_free);
1333 ensure(_mode_lock_ct == old_mode_lock_ct - 1);
1337 pthread_mutex_unlock(&read_write_monitor_mutex);
1387 ensure(result != 0);
1424 result = result && _ro_ct >= 0;
1425 result = result && _mode_lock_ct >= 0;
1426 result = result && ( (_rw_ct == 0) || (_rw_ct == 1) );
1427 result = result && !( (_rw_ct == 1) && (_ro_ct > 0) );
virtual bool invariant() const
Class invariant.
virtual bool is_ancestor_of(const any *xother) const
True if other conforms to current.
The monitor concurrency control interface. Class READ_WRITE_MONITOR implements the monitor concurrenc...
void enable_access_guards()
Re-enables access guards.
bool is_not_read_only_accessible() const
True if this thread does not have read-only access.
void get_read_access() const
Get read access to the state associated with this.
void clear_is_modified()
Makes is_modified() false.
bool is_read_write_accessible() const
True if this thread has read-write access or if access control is not enabled.
virtual read_write_monitor * clone() const
Make a new instance of the same type as this.
void get_read_write_access(bool xrelease_read_only_access=false)
Get read write access to the state associated with this. If release_read_only_access is requested...
Abstract base class with useful features for all objects.
bool is_mode_locked() const
bool access_guards_disabled() const
True if access guards disabled.
int access_request_depth() const
Number of times access has been granted without a corresponding release.
void release_access(bool xall=false) const
Release access. If xall is true, release all levels of access. Otherwise, release one level of access...
void disable_access_guards()
Disables access gaurds; intended for use only within constructors of monitored objects, where no other client can possibly have access (yet).
bool is_read_only_accessible() const
True if this thread has read-only access.
read_write_monitor()
Default Constructor.
bool is_not_read_accessible() const
True if this thread has neither read-only or read-write access or if access control is disabled...
void disable_invariant_check() const
Disable invariant check. Intended for preventing recursive calls to invariant and for suppressing inv...
bool is_not_read_write_accessible() const
True if this thread does not have read-write access or if access control is not enabled.
bool invariant_check() const
True if invariant checking is enabled.
static bool access_control_disabled()
True if access control mechanism is disabled. Default value is enabled (false) and access is controll...
bool is_modified() const
True if any client has had read-write access to this object since the last call to clear_is_modified(...
virtual ~read_write_monitor()
Destructor.
void enable_invariant_check() const
Enable invariant checking.
bool is_read_accessible() const
True if this thread has read-only or read-write access.
static void enable_access_control()
Enables access control. Should only be invoked once at beginning of a program, before any other Sheaf...