android flockfile.c

#include <stdio.h> #include <pthread.h> #include <string.h> /* a node in the hash table */ typedef struct FileLock { struct FileLock* next; FILE* file; pthread_mutex_t mutex; } FileLock; /* use a static hash table. We assume that we're not going to * lock a really large number of FILE* objects on an embedded * system. */ #define FILE_LOCK_BUCKETS 32 typedef struct { pthread_mutex_t lock; FileLock* buckets[ FILE_LOCK_BUCKETS ]; } LockTable; static LockTable* _lockTable; static pthread_once_t _lockTable_once = PTHREAD_ONCE_INIT; static void lock_table_init( void ) { _lockTable = malloc(sizeof(*_lockTable)); if (_lockTable != NULL) { pthread_mutex_init(&_lockTable->lock, NULL); memset(_lockTable->buckets, 0, sizeof(_lockTable->buckets)); } } static LockTable* lock_table_lock( void ) { pthread_once( &_lockTable_once, lock_table_init ); pthread_mutex_lock( &_lockTable->lock ); return _lockTable; } static void lock_table_unlock( LockTable* t ) { pthread_mutex_unlock( &t->lock ); } static FileLock** lock_table_lookup( LockTable* t, FILE* f ) { uint32_t hash = (uint32_t)(void*)f; FileLock** pnode; hash = (hash >> 2) ^ (hash << 17); pnode = &t->buckets[hash % FILE_LOCK_BUCKETS]; for (;;) { FileLock* node = *pnode; if (node == NULL || node->file == f) break; pnode = &node->next; } return pnode; } void flockfile(FILE * fp) { LockTable* t = lock_table_lock(); if (t != NULL) { FileLock** lookup = lock_table_lookup(t, fp); FileLock* lock = *lookup; if (lock == NULL) { pthread_mutexattr_t attr; /* create a new node in the hash table */ lock = malloc(sizeof(*lock)); if (lock == NULL) { lock_table_unlock(t); return; } lock->next = NULL; lock->file = fp; pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); pthread_mutex_init( &lock->mutex, &attr ); *lookup = lock; } lock_table_unlock(t); /* we assume that another thread didn't destroy 'lock' * by calling fclose() on the FILE*. This can happen if * the client is *really* buggy, but we don't care about * such code here. */ pthread_mutex_lock(&lock->mutex); } } int ftrylockfile(FILE *fp) { int ret = -1; LockTable* t = lock_table_lock(); if (t != NULL) { FileLock** lookup = lock_table_lookup(t, fp); FileLock* lock = *lookup; lock_table_unlock(t); /* see above comment about why we assume that 'lock' can * be accessed from here */ if (lock != NULL && !pthread_mutex_trylock(&lock->mutex)) { ret = 0; /* signal success */ } } return ret; } void funlockfile(FILE * fp) { LockTable* t = lock_table_lock(); if (t != NULL) { FileLock** lookup = lock_table_lookup(t, fp); FileLock* lock = *lookup; if (lock != NULL) pthread_mutex_unlock(&lock->mutex); lock_table_unlock(t); } } /* called from fclose() to remove the file lock */ __LIBC_HIDDEN__ void __fremovelock(FILE* fp) { LockTable* t = lock_table_lock(); if (t != NULL) { FileLock** lookup = lock_table_lookup(t, fp); FileLock* lock = *lookup; if (lock != NULL) { *lookup = lock->next; lock->file = NULL; } lock_table_unlock(t); free(lock); } }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章