Skip to content

Commit 4ccb570

Browse files
author
David Berry
committed
Allow locks to be read-only or read-write
1 parent 8888a46 commit 4ccb570

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+685
-321
lines changed

dat1.h

+17-19
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
*-
7373
*/
7474

75+
#include <pthread.h>
7576
#include "hdf5.h"
7677
#include "hdf5_hl.h"
7778
#include "hds1.h"
@@ -141,24 +142,20 @@ typedef enum {
141142
/* This structure contains information about an HDF5 object (group or
142143
dataset) that is common to all the locators that refer to the object. */
143144
typedef struct Handle {
144-
char locked; /* Non-zero if the HDF object is currently locked for
145-
access by a single thread. Zero if the object is
146-
unlocked. */
147-
pthread_t locker; /* Id for the thread that has locked the object (if
148-
any) */
149-
struct Handle *parent; /* Pointer to Handle describing the parent object */
150-
struct Handle **children; /* Pointer to array holding pointers to Handles
151-
for any known child objects */
152-
int nchild; /* The length of the "children" array */
153-
char *name; /* Name (cleaned) of the HDF object within its parent */
154-
pthread_mutex_t mutex2; /* Guards access to the values in the handle */
155-
156-
} Handle;
145+
pthread_mutex_t mutex; /* Guards access to the values in the handle */
157146

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

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

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

432-
Handle *dat1Handle( const HDSLoc *parent_loc, const char *name, int * status );
429+
Handle *dat1Handle( const HDSLoc *parent_loc, const char *name, int
430+
rdonly, int * status );
433431
Handle *dat1EraseHandle( Handle *parent, const char *name, int * status );
434432
Handle *dat1FreeHandle( Handle *handle );
435-
int dat1ValidateLocator( int checklock, const HDSLoc *loc, int *status );
436-
int dat1HandleLock( Handle *handle, int oper, int recurs, int *status );
433+
int dat1ValidateLocator( const char *func, int checklock, const HDSLoc *loc, int rdonly, int *status );
434+
int dat1HandleLock( Handle *handle, int oper, int recurs, int rdonly, int *status );
437435
void dat1HandleMsg( const char *token, const Handle *handle );
438436

439437
/* DAT1_H_INCLUDED */

dat1FreeHandle.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,10 @@ Handle *dat1FreeHandle( Handle *handle ) {
9494
/* Free the memory used by components of the Handle structure. */
9595
if( handle->name ) MEM_FREE( handle->name );
9696
if( handle->children ) MEM_FREE( handle->children );
97+
if( handle->read_lockers ) MEM_FREE( handle->read_lockers );
9798

9899
/* Destroy the mutex */
99-
pthread_mutex_destroy( &(handle->mutex2) );
100+
pthread_mutex_destroy( &(handle->mutex) );
100101

101102
/* Fill the handles with zeros in case any other points to the same
102103
handle exist. */

dat1Handle.c

+45-11
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
* Library routine
1414
1515
* Invocation:
16-
* Handle *dat1Handle( const HDSLoc *parent, const char *name, int *status );
16+
* Handle *dat1Handle( const HDSLoc *parent, const char *name,
17+
* int rdonly, int *status );
1718
1819
* Arguments:
1920
* parent = const HDSLoc * (Given)
@@ -26,6 +27,14 @@
2627
* component does in fact exist within the parent object, although
2728
* this is not checked. If "parent" is NULL, the path to the
2829
* contained file should be supplied.
30+
* rdonly = int (Given)
31+
* If a new Handle is created as a result of calling this function,
32+
* it is locked for use by the current thread. If "parent" is
33+
* non-NULL, the type of lock (read-only or read-write) is copied
34+
* from the parent. If "parent" is NULL, the type of lock is
35+
* specified by the "rdonly" argument. The supplied "rdonly" value
36+
* is ignored if "parent" is non-NULL or if a pointer to an existing
37+
* handle is returned.
2938
* status = int* (Given and Returned)
3039
* Pointer to global status.
3140
@@ -103,7 +112,8 @@
103112
#include "dat1.h"
104113
#include "dat_err.h"
105114

106-
Handle *dat1Handle( const HDSLoc *parent_loc, const char *name, int * status ){
115+
Handle *dat1Handle( const HDSLoc *parent_loc, const char *name, int rdonly,
116+
int * status ){
107117

108118

109119
/* Local Variables; */
@@ -112,6 +122,7 @@ Handle *dat1Handle( const HDSLoc *parent_loc, const char *name, int * status ){
112122
Handle *parent;
113123
Handle *result = NULL;
114124
int ichild;
125+
int lock_status;
115126

116127
/* Return immediately if an error has already occurred. */
117128
if( *status != SAI__OK ) return result;
@@ -121,7 +132,7 @@ Handle *dat1Handle( const HDSLoc *parent_loc, const char *name, int * status ){
121132
lname = MEM_CALLOC( strlen( name ) + 1, sizeof(char) );
122133
if( !lname ) {
123134
*status = DAT__NOMEM;
124-
emsRep("dat1Handle", "Could not reallocate memory for the "
135+
emsRep("dat1Handle", "Could not allocate memory for the "
125136
"component name in an HDS Handle", status );
126137
} else {
127138
strcpy( lname, name );
@@ -175,9 +186,6 @@ Handle *dat1Handle( const HDSLoc *parent_loc, const char *name, int * status ){
175186
parent->children[ parent->nchild-1 ] = result;
176187
}
177188

178-
/* Copy other information from the parent Handle. */
179-
result->locked = parent->locked;
180-
result->locker = parent->locker;
181189
}
182190

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

196-
/* Indicate the Handle is locked for use by the current thread. */
197-
result->locked = 1;
198-
result->locker = pthread_self();
205+
/* Initialise the Handle to indicate it is currently unlocked. */
206+
result->nwrite_lock = 0;
207+
result->nread_lock = 0;
208+
result->read_lockers = NULL;
209+
result->maxreaders = 0;
210+
211+
/* If a parent was supplied, see if the current thread has a read or
212+
write lock on the parent object. We give the same sort of lock to the
213+
new Handle below (ignoring the supplied value for "rdonly"). */
214+
if( parent ) {
215+
lock_status = dat1HandleLock( parent, 1, 0, 0, status );
216+
if( lock_status == 1 ) {
217+
rdonly = 0;
218+
} else if( lock_status == 3 ) {
219+
rdonly = 1;
220+
} else if( *status == SAI__OK ) {
221+
*status = DAT__FATAL;
222+
emsRepf( " ", "dat1Handle: Unexpected lock value (%d) for "
223+
"object '%s' - parent of '%s' (internal HDS "
224+
"programming error).", status, lock_status,
225+
parent->name, name );
226+
}
227+
}
228+
229+
/* Lock the new Handle for use by the current thread. The type of lock
230+
(read-only or read-write) is inherited from the parent (if there is a
231+
parent) or supplied by the caller. */
232+
dat1HandleLock( result, 2, 0, rdonly, status );
199233
}
200234
}
201235

0 commit comments

Comments
 (0)