Skip to content

Commit

Permalink
Allow locks to be read-only or read-write
Browse files Browse the repository at this point in the history
  • Loading branch information
David Berry committed Jul 25, 2017
1 parent 8888a46 commit 4ccb570
Show file tree
Hide file tree
Showing 62 changed files with 685 additions and 321 deletions.
36 changes: 17 additions & 19 deletions dat1.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
*-
*/

#include <pthread.h>
#include "hdf5.h"
#include "hdf5_hl.h"
#include "hds1.h"
Expand Down Expand Up @@ -141,24 +142,20 @@ typedef enum {
/* This structure contains information about an HDF5 object (group or
dataset) that is common to all the locators that refer to the object. */
typedef struct Handle {
char locked; /* Non-zero if the HDF object is currently locked for
access by a single thread. Zero if the object is
unlocked. */
pthread_t locker; /* Id for the thread that has locked the object (if
any) */
struct Handle *parent; /* Pointer to Handle describing the parent object */
struct Handle **children; /* Pointer to array holding pointers to Handles
for any known child objects */
int nchild; /* The length of the "children" array */
char *name; /* Name (cleaned) of the HDF object within its parent */
pthread_mutex_t mutex2; /* Guards access to the values in the handle */

} Handle;
pthread_mutex_t mutex; /* Guards access to the values in the handle */

/* Define functions to lock and unlock a Handle's mutex. */
#define DAT_LOCK_MUTEX2(han) pthread_mutex_lock( &((han)->mutex2) )
#define DAT_UNLOCK_MUTEX2(han) pthread_mutex_unlock( &((han)->mutex2) )
int nwrite_lock; /* Number of current write locks (0 or 1) */
pthread_t write_locker; /* ID for thread holding write lock */
int nread_lock; /* Number of current read locks (0 or more) */
pthread_t *read_lockers; /* Array of IDs for thread holding read locks */
int maxreaders; /* Current size of "read_lockers" array */

struct Handle *parent; /* Pointer to Handle describing the parent object */
struct Handle **children;/* Pointer to array holding pointers to Handles
for any known child objects */
int nchild; /* The length of the "children" array */
char *name; /* Name (cleaned) of the HDF object within its parent */
} Handle;

/* Private definition of the HDS locator struct */
typedef struct LOC {
Expand Down Expand Up @@ -429,11 +426,12 @@ dat1GetStructureDims( const HDSLoc * locator, int maxdims, hdsdim dims[], int *s
hdsbool_t
dat1NeedsRootName( hid_t objid, hdsbool_t wantprim, char * rootname, size_t rootnamelen, int * status );

Handle *dat1Handle( const HDSLoc *parent_loc, const char *name, int * status );
Handle *dat1Handle( const HDSLoc *parent_loc, const char *name, int
rdonly, int * status );
Handle *dat1EraseHandle( Handle *parent, const char *name, int * status );
Handle *dat1FreeHandle( Handle *handle );
int dat1ValidateLocator( int checklock, const HDSLoc *loc, int *status );
int dat1HandleLock( Handle *handle, int oper, int recurs, int *status );
int dat1ValidateLocator( const char *func, int checklock, const HDSLoc *loc, int rdonly, int *status );
int dat1HandleLock( Handle *handle, int oper, int recurs, int rdonly, int *status );
void dat1HandleMsg( const char *token, const Handle *handle );

/* DAT1_H_INCLUDED */
Expand Down
3 changes: 2 additions & 1 deletion dat1FreeHandle.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,10 @@ Handle *dat1FreeHandle( Handle *handle ) {
/* Free the memory used by components of the Handle structure. */
if( handle->name ) MEM_FREE( handle->name );
if( handle->children ) MEM_FREE( handle->children );
if( handle->read_lockers ) MEM_FREE( handle->read_lockers );

/* Destroy the mutex */
pthread_mutex_destroy( &(handle->mutex2) );
pthread_mutex_destroy( &(handle->mutex) );

/* Fill the handles with zeros in case any other points to the same
handle exist. */
Expand Down
56 changes: 45 additions & 11 deletions dat1Handle.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
* Library routine
* Invocation:
* Handle *dat1Handle( const HDSLoc *parent, const char *name, int *status );
* Handle *dat1Handle( const HDSLoc *parent, const char *name,
* int rdonly, int *status );
* Arguments:
* parent = const HDSLoc * (Given)
Expand All @@ -26,6 +27,14 @@
* component does in fact exist within the parent object, although
* this is not checked. If "parent" is NULL, the path to the
* contained file should be supplied.
* rdonly = int (Given)
* If a new Handle is created as a result of calling this function,
* it is locked for use by the current thread. If "parent" is
* non-NULL, the type of lock (read-only or read-write) is copied
* from the parent. If "parent" is NULL, the type of lock is
* specified by the "rdonly" argument. The supplied "rdonly" value
* is ignored if "parent" is non-NULL or if a pointer to an existing
* handle is returned.
* status = int* (Given and Returned)
* Pointer to global status.
Expand Down Expand Up @@ -103,7 +112,8 @@
#include "dat1.h"
#include "dat_err.h"

Handle *dat1Handle( const HDSLoc *parent_loc, const char *name, int * status ){
Handle *dat1Handle( const HDSLoc *parent_loc, const char *name, int rdonly,
int * status ){


/* Local Variables; */
Expand All @@ -112,6 +122,7 @@ Handle *dat1Handle( const HDSLoc *parent_loc, const char *name, int * status ){
Handle *parent;
Handle *result = NULL;
int ichild;
int lock_status;

/* Return immediately if an error has already occurred. */
if( *status != SAI__OK ) return result;
Expand All @@ -121,7 +132,7 @@ Handle *dat1Handle( const HDSLoc *parent_loc, const char *name, int * status ){
lname = MEM_CALLOC( strlen( name ) + 1, sizeof(char) );
if( !lname ) {
*status = DAT__NOMEM;
emsRep("dat1Handle", "Could not reallocate memory for the "
emsRep("dat1Handle", "Could not allocate memory for the "
"component name in an HDS Handle", status );
} else {
strcpy( lname, name );
Expand Down Expand Up @@ -175,9 +186,6 @@ Handle *dat1Handle( const HDSLoc *parent_loc, const char *name, int * status ){
parent->children[ parent->nchild-1 ] = result;
}

/* Copy other information from the parent Handle. */
result->locked = parent->locked;
result->locker = parent->locker;
}

/* Store the component name. Nullify "lname" to indicate the memory is
Expand All @@ -188,14 +196,40 @@ Handle *dat1Handle( const HDSLoc *parent_loc, const char *name, int * status ){
/* Initialise a mutex that is used to serialise access to the values
stored in the handle. */
if( *status == SAI__OK &&
pthread_mutex_init( &(result->mutex2), NULL ) != 0 ) {
emsRep( " ", "Failed to initialise POSIX mutex2 for a new Handle.",
pthread_mutex_init( &(result->mutex), NULL ) != 0 ) {
*status = DAT__MUTEX;
emsRep( " ", "Failed to initialise POSIX mutex for a new Handle.",
status );
}

/* Indicate the Handle is locked for use by the current thread. */
result->locked = 1;
result->locker = pthread_self();
/* Initialise the Handle to indicate it is currently unlocked. */
result->nwrite_lock = 0;
result->nread_lock = 0;
result->read_lockers = NULL;
result->maxreaders = 0;

/* If a parent was supplied, see if the current thread has a read or
write lock on the parent object. We give the same sort of lock to the
new Handle below (ignoring the supplied value for "rdonly"). */
if( parent ) {
lock_status = dat1HandleLock( parent, 1, 0, 0, status );
if( lock_status == 1 ) {
rdonly = 0;
} else if( lock_status == 3 ) {
rdonly = 1;
} else if( *status == SAI__OK ) {
*status = DAT__FATAL;
emsRepf( " ", "dat1Handle: Unexpected lock value (%d) for "
"object '%s' - parent of '%s' (internal HDS "
"programming error).", status, lock_status,
parent->name, name );
}
}

/* Lock the new Handle for use by the current thread. The type of lock
(read-only or read-write) is inherited from the parent (if there is a
parent) or supplied by the caller. */
dat1HandleLock( result, 2, 0, rdonly, status );
}
}

Expand Down
Loading

0 comments on commit 4ccb570

Please sign in to comment.