forked from GitHub/gf-core
finished porting to Windows
This commit is contained in:
@@ -22,6 +22,21 @@ size_t getpagesize()
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define ftruncate _chsize
|
#define ftruncate _chsize
|
||||||
|
|
||||||
|
static
|
||||||
|
int last_error_to_errno()
|
||||||
|
{
|
||||||
|
switch (GetLastError()) {
|
||||||
|
case ERROR_SUCCESS:
|
||||||
|
return 0;
|
||||||
|
case ERROR_OUTOFMEMORY:
|
||||||
|
return ENOMEM;
|
||||||
|
case ERROR_HANDLE_DISK_FULL:
|
||||||
|
return ENOSPC;
|
||||||
|
default:
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PGF_INTERNAL __thread unsigned char* current_base __attribute__((tls_model("initial-exec"))) = NULL;
|
PGF_INTERNAL __thread unsigned char* current_base __attribute__((tls_model("initial-exec"))) = NULL;
|
||||||
@@ -300,6 +315,11 @@ struct PGF_INTERNAL_DECL malloc_state
|
|||||||
*/
|
*/
|
||||||
ref<PgfPGF> transient_revisions;
|
ref<PgfPGF> transient_revisions;
|
||||||
ref<PgfConcr> transient_concr_revisions;
|
ref<PgfConcr> transient_concr_revisions;
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
/* Stores a Reader/Writer lock for Windows */
|
||||||
|
LONG lock;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
PGF_INTERNAL
|
PGF_INTERNAL
|
||||||
@@ -342,29 +362,62 @@ PgfDB::PgfDB(const char* filepath, int flags, int mode) {
|
|||||||
this->filepath = strdup(filepath);
|
this->filepath = strdup(filepath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int code = 0;
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
#ifndef MREMAP_MAYMOVE
|
#ifndef MREMAP_MAYMOVE
|
||||||
if (fd >= 0) {
|
if (fd >= 0) {
|
||||||
ms = (malloc_state*)
|
ms = (malloc_state*)
|
||||||
mmap(NULL, file_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
mmap(NULL, file_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||||
|
code = errno;
|
||||||
} else {
|
} else {
|
||||||
ms = (malloc_state*) ::malloc(file_size);
|
ms = (malloc_state*) ::malloc(file_size);
|
||||||
|
code = ENOMEM;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
int mflags = (fd < 0) ? (MAP_PRIVATE | MAP_ANONYMOUS) : MAP_SHARED;
|
int mflags = (fd < 0) ? (MAP_PRIVATE | MAP_ANONYMOUS) : MAP_SHARED;
|
||||||
ms = (malloc_state*)
|
ms = (malloc_state*)
|
||||||
mmap(NULL, file_size, PROT_READ | PROT_WRITE, mflags, fd, 0);
|
mmap(NULL, file_size, PROT_READ | PROT_WRITE, mflags, fd, 0);
|
||||||
|
code = errno;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ms == MAP_FAILED || ms == NULL) {
|
if (ms == MAP_FAILED || ms == NULL) {
|
||||||
ms = NULL; // mark that ms is not created.
|
ms = NULL; // mark that ms is not created.
|
||||||
::free((void *) this->filepath);
|
::free((void *) this->filepath);
|
||||||
int code = errno;
|
|
||||||
close(fd);
|
close(fd);
|
||||||
throw pgf_systemerror(code, filepath);
|
throw pgf_systemerror(code, filepath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
rwlock = ipc_new_file_rwlock(this->filepath, &is_first);
|
||||||
|
} catch (pgf_systemerror e) {
|
||||||
|
#ifndef MREMAP_MAYMOVE
|
||||||
|
if (fd < 0) {
|
||||||
|
::free(ms);
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
munmap(ms,file_size);
|
||||||
|
|
||||||
|
::free((void *) this->filepath);
|
||||||
|
close(fd);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
|
char *name;
|
||||||
|
char buf[256];
|
||||||
|
|
||||||
if (fd >= 0) {
|
if (fd >= 0) {
|
||||||
|
BY_HANDLE_FILE_INFORMATION hInfo;
|
||||||
|
if (!GetFileInformationByHandle((HANDLE) _get_osfhandle(fd), &hInfo)) {
|
||||||
|
code = last_error_to_errno();
|
||||||
|
::free((void *) this->filepath);
|
||||||
|
close(fd);
|
||||||
|
throw pgf_systemerror(code);
|
||||||
|
}
|
||||||
|
sprintf(buf, "gf-rwevent-%lx-%lx-%lx",
|
||||||
|
hInfo.dwVolumeSerialNumber,
|
||||||
|
hInfo.nFileIndexHigh,
|
||||||
|
hInfo.nFileIndexLow);
|
||||||
|
name = buf;
|
||||||
|
|
||||||
hMap = CreateFileMapping((HANDLE) _get_osfhandle(fd),
|
hMap = CreateFileMapping((HANDLE) _get_osfhandle(fd),
|
||||||
NULL,
|
NULL,
|
||||||
PAGE_READWRITE,
|
PAGE_READWRITE,
|
||||||
@@ -375,49 +428,41 @@ PgfDB::PgfDB(const char* filepath, int flags, int mode) {
|
|||||||
FILE_MAP_WRITE,
|
FILE_MAP_WRITE,
|
||||||
0,0,file_size);
|
0,0,file_size);
|
||||||
if (ms == NULL) {
|
if (ms == NULL) {
|
||||||
|
code = last_error_to_errno();
|
||||||
CloseHandle(hMap);
|
CloseHandle(hMap);
|
||||||
hMap = INVALID_HANDLE_VALUE;
|
hMap = INVALID_HANDLE_VALUE;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
code = last_error_to_errno();
|
||||||
hMap = INVALID_HANDLE_VALUE;
|
hMap = INVALID_HANDLE_VALUE;
|
||||||
ms = NULL;
|
ms = NULL;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
code = ENOMEM;
|
||||||
|
name = NULL;
|
||||||
hMap = INVALID_HANDLE_VALUE;
|
hMap = INVALID_HANDLE_VALUE;
|
||||||
ms = (malloc_state*) ::malloc(file_size);
|
ms = (malloc_state*) ::malloc(file_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ms == NULL) {
|
if (ms == NULL) {
|
||||||
::free((void *) this->filepath);
|
::free((void *) this->filepath);
|
||||||
int code = errno;
|
|
||||||
close(fd);
|
close(fd);
|
||||||
throw pgf_systemerror(code, filepath);
|
throw pgf_systemerror(code, filepath);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
try {
|
hRWEvent = CreateEvent(NULL, FALSE, FALSE, name);
|
||||||
rwlock = ipc_new_file_rwlock(this->filepath, &is_first);
|
if (hRWEvent == NULL) {
|
||||||
} catch (pgf_systemerror e) {
|
|
||||||
#ifndef _WIN32
|
|
||||||
#ifndef MREMAP_MAYMOVE
|
|
||||||
if (fd < 0) {
|
|
||||||
::free(ms);
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
munmap(ms,file_size);
|
|
||||||
#else
|
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
::free(ms);
|
::free(ms);
|
||||||
} else {
|
} else {
|
||||||
UnmapViewOfFile(ms);
|
UnmapViewOfFile(ms);
|
||||||
CloseHandle(hMap);
|
CloseHandle(hMap);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
::free((void *) this->filepath);
|
::free((void *) this->filepath);
|
||||||
close(fd);
|
close(fd);
|
||||||
throw e;
|
throw pgf_systemerror(code, filepath);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (is_new) {
|
if (is_new) {
|
||||||
init_state(file_size);
|
init_state(file_size);
|
||||||
@@ -437,6 +482,7 @@ PgfDB::PgfDB(const char* filepath, int flags, int mode) {
|
|||||||
UnmapViewOfFile(ms);
|
UnmapViewOfFile(ms);
|
||||||
CloseHandle(hMap);
|
CloseHandle(hMap);
|
||||||
}
|
}
|
||||||
|
CloseHandle(hRWEvent);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
::free((void *) this->filepath);
|
::free((void *) this->filepath);
|
||||||
@@ -493,13 +539,16 @@ PgfDB::~PgfDB() {
|
|||||||
UnmapViewOfFile(ms);
|
UnmapViewOfFile(ms);
|
||||||
CloseHandle(hMap);
|
CloseHandle(hMap);
|
||||||
}
|
}
|
||||||
|
CloseHandle(hRWEvent);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fd >= 0)
|
if (fd >= 0)
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
ipc_release_file_rwlock(filepath, rwlock);
|
ipc_release_file_rwlock(filepath, rwlock);
|
||||||
|
#endif
|
||||||
|
|
||||||
::free((void*) filepath);
|
::free((void*) filepath);
|
||||||
}
|
}
|
||||||
@@ -550,6 +599,10 @@ void PgfDB::init_state(size_t size)
|
|||||||
ms->revisions = 0;
|
ms->revisions = 0;
|
||||||
ms->transient_revisions = 0;
|
ms->transient_revisions = 0;
|
||||||
ms->transient_concr_revisions = 0;
|
ms->transient_concr_revisions = 0;
|
||||||
|
|
||||||
|
#if _WIN32
|
||||||
|
ms->lock = 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Take a chunk off a bin list. */
|
/* Take a chunk off a bin list. */
|
||||||
@@ -1005,30 +1058,61 @@ object PgfDB::malloc_internal(size_t bytes)
|
|||||||
size_t new_size =
|
size_t new_size =
|
||||||
old_size + alloc_size;
|
old_size + alloc_size;
|
||||||
|
|
||||||
if (fd >= 0) {
|
|
||||||
if (ftruncate(fd, new_size) < 0)
|
|
||||||
throw pgf_systemerror(errno, filepath);
|
|
||||||
}
|
|
||||||
|
|
||||||
malloc_state* new_ms;
|
malloc_state* new_ms;
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
// OSX mman and mman-win32 do not implement mremap or MREMAP_MAYMOVE
|
// OSX do not implement mremap or MREMAP_MAYMOVE
|
||||||
#ifndef MREMAP_MAYMOVE
|
#ifndef MREMAP_MAYMOVE
|
||||||
if (fd >= 0) {
|
if (fd >= 0) {
|
||||||
if (munmap(ms, old_size) == -1)
|
if (munmap(ms, old_size) == -1)
|
||||||
throw pgf_systemerror(errno);
|
throw pgf_systemerror(errno);
|
||||||
|
ms = NULL;
|
||||||
|
if (ftruncate(fd, new_size) < 0)
|
||||||
|
throw pgf_systemerror(errno, filepath);
|
||||||
new_ms =
|
new_ms =
|
||||||
(malloc_state*) mmap(0, new_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
(malloc_state*) mmap(0, new_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||||
|
if (new_ms == MAP_FAILED)
|
||||||
|
throw pgf_systemerror(errno);
|
||||||
} else {
|
} else {
|
||||||
new_ms = (malloc_state*) realloc(ms, new_size);
|
new_ms = (malloc_state*) realloc(ms, new_size);
|
||||||
|
if (new_ms == NULL)
|
||||||
|
throw pgf_systemerror(ENOMEM);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
if (fd >= 0) {
|
||||||
|
if (ftruncate(fd, new_size) < 0)
|
||||||
|
throw pgf_systemerror(errno, filepath);
|
||||||
|
}
|
||||||
new_ms =
|
new_ms =
|
||||||
(malloc_state*) mremap(ms, old_size, new_size, MREMAP_MAYMOVE);
|
(malloc_state*) mremap(ms, old_size, new_size, MREMAP_MAYMOVE);
|
||||||
#endif
|
|
||||||
if (new_ms == MAP_FAILED)
|
if (new_ms == MAP_FAILED)
|
||||||
throw pgf_systemerror(errno);
|
throw pgf_systemerror(errno);
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
|
if (fd >= 0) {
|
||||||
|
UnmapViewOfFile(ms);
|
||||||
|
CloseHandle(hMap);
|
||||||
|
ms = NULL;
|
||||||
|
|
||||||
|
hMap = CreateFileMapping((HANDLE) _get_osfhandle(fd),
|
||||||
|
NULL,
|
||||||
|
PAGE_READWRITE,
|
||||||
|
HIWORD(new_size), LOWORD(new_size),
|
||||||
|
NULL);
|
||||||
|
if (hMap == NULL) {
|
||||||
|
hMap = INVALID_HANDLE_VALUE;
|
||||||
|
throw pgf_systemerror(last_error_to_errno());
|
||||||
|
}
|
||||||
|
|
||||||
|
new_ms = (malloc_state*) MapViewOfFile(hMap,
|
||||||
|
FILE_MAP_WRITE,
|
||||||
|
0,0,new_size);
|
||||||
|
if (new_ms == NULL)
|
||||||
|
throw pgf_systemerror(last_error_to_errno());
|
||||||
|
} else {
|
||||||
|
new_ms = (malloc_state*) realloc(ms, new_size);
|
||||||
|
if (new_ms == NULL)
|
||||||
|
throw pgf_systemerror(ENOMEM);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ms = new_ms;
|
ms = new_ms;
|
||||||
@@ -1246,16 +1330,142 @@ void PgfDB::sync()
|
|||||||
if (res != 0)
|
if (res != 0)
|
||||||
throw pgf_systemerror(errno);
|
throw pgf_systemerror(errno);
|
||||||
#else
|
#else
|
||||||
|
if (current_db->fd > 0) {
|
||||||
|
if (!FlushViewOfFile(ms,size)) {
|
||||||
|
throw pgf_systemerror(last_error_to_errno());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define MAX_SPIN 50000
|
||||||
|
|
||||||
|
__forceinline __int16 ReaderCount(unsigned __int32 lock)
|
||||||
|
{
|
||||||
|
return lock & 0x00007FFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
__forceinline __int32 SetReaders(unsigned __int32 lock, unsigned __int16 readers)
|
||||||
|
{
|
||||||
|
return (lock & ~0x00007FFF) | readers;
|
||||||
|
}
|
||||||
|
|
||||||
|
__forceinline __int16 WaitingCount(unsigned __int32 lock)
|
||||||
|
{
|
||||||
|
return (__int16) ((lock & 0x3FFF8000) >> 15);
|
||||||
|
}
|
||||||
|
|
||||||
|
__forceinline __int32 SetWaiting(unsigned __int32 lock, unsigned __int16 waiting)
|
||||||
|
{
|
||||||
|
return (lock & ~0x3FFF8000) | (waiting << 15);
|
||||||
|
}
|
||||||
|
|
||||||
|
__forceinline bool Writer(unsigned __int32 lock)
|
||||||
|
{
|
||||||
|
return (lock & 0x40000000) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
__forceinline __int32 SetWriter(unsigned __int32 lock, bool writer)
|
||||||
|
{
|
||||||
|
if(writer)
|
||||||
|
return lock | 0x40000000;
|
||||||
|
else
|
||||||
|
return lock & ~0x40000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
__forceinline bool AllClear(unsigned __int32 lock)
|
||||||
|
{
|
||||||
|
return (lock & 0x40007FFF) == 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void PgfDB::lock(DB_scope_mode m)
|
||||||
|
{
|
||||||
|
#ifndef _WIN32
|
||||||
|
int res =
|
||||||
|
(m == READER_SCOPE) ? pthread_rwlock_rdlock(rwlock)
|
||||||
|
: pthread_rwlock_wrlock(rwlock);
|
||||||
|
if (res != 0)
|
||||||
|
throw pgf_systemerror(res);
|
||||||
|
#else
|
||||||
|
for (int i = 0; ; ++i) {
|
||||||
|
unsigned __int32 temp = ms->lock;
|
||||||
|
if (m == READER_SCOPE && !Writer(temp)) {
|
||||||
|
if (InterlockedCompareExchange(&ms->lock, SetReaders(temp, ReaderCount(temp) + 1), temp) == temp)
|
||||||
|
return;
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
} else if (m == WRITER_SCOPE && AllClear(temp)) {
|
||||||
|
if (InterlockedCompareExchange(&ms->lock, SetWriter(temp, true), temp) == temp)
|
||||||
|
return;
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
if (i < MAX_SPIN) {
|
||||||
|
YieldProcessor();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//The pending write operation is taking too long, so we'll drop to the kernel and wait
|
||||||
|
if (InterlockedCompareExchange(&ms->lock, SetWaiting(temp, WaitingCount(temp) + 1), temp) != temp)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
i = 0; //Reset the spincount for the next time
|
||||||
|
WaitForSingleObject(hRWEvent, INFINITE);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
temp = ms->lock;
|
||||||
|
} while (InterlockedCompareExchange(&ms->lock, SetWaiting(temp, WaitingCount(temp) - 1), temp) != temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void PgfDB::unlock()
|
||||||
|
{
|
||||||
|
#ifndef _WIN32
|
||||||
|
pthread_rwlock_unlock(rwlock);
|
||||||
|
#else
|
||||||
|
while (true) {
|
||||||
|
unsigned __int32 temp = ms->lock;
|
||||||
|
if (ReaderCount(temp) > 0) {
|
||||||
|
if (ReaderCount(temp) == 1 && WaitingCount(temp) != 0) {
|
||||||
|
//Note: this isn't nor has to be thread-safe, as the worst a duplicate notification can do
|
||||||
|
//is cause a waiting to reader to wake, perform a spinlock, then go back to sleep
|
||||||
|
|
||||||
|
//We're the last reader and there's a pending write
|
||||||
|
//Wake one waiting writer
|
||||||
|
SetEvent(hRWEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Decrement reader count
|
||||||
|
if (InterlockedCompareExchange(&ms->lock, SetReaders(temp, ReaderCount(temp) - 1), temp) == temp)
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
while(true) {
|
||||||
|
temp = ms->lock;
|
||||||
|
assert(Writer(temp));
|
||||||
|
if (WaitingCount(temp) == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
//Note: this is thread-safe (there's guaranteed not to be another EndWrite simultaneously)
|
||||||
|
//Wake all waiting readers or writers, loop until wake confirmation is received
|
||||||
|
SetEvent(hRWEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Decrement writer count
|
||||||
|
if (InterlockedCompareExchange(&ms->lock, SetWriter(temp, false), temp) == temp)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
DB_scope::DB_scope(PgfDB *db, DB_scope_mode m)
|
DB_scope::DB_scope(PgfDB *db, DB_scope_mode m)
|
||||||
{
|
{
|
||||||
int res =
|
db->lock(m);
|
||||||
(m == READER_SCOPE) ? ipc_rwlock_rdlock(db->rwlock)
|
|
||||||
: ipc_rwlock_wrlock(db->rwlock);
|
|
||||||
if (res != 0)
|
|
||||||
throw pgf_systemerror(res);
|
|
||||||
|
|
||||||
save_db = current_db;
|
save_db = current_db;
|
||||||
current_db = db;
|
current_db = db;
|
||||||
@@ -1269,7 +1479,7 @@ DB_scope::~DB_scope()
|
|||||||
{
|
{
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wterminate"
|
#pragma GCC diagnostic ignored "-Wterminate"
|
||||||
ipc_rwlock_unlock(current_db->rwlock);
|
current_db->unlock();
|
||||||
|
|
||||||
current_db = save_db;
|
current_db = save_db;
|
||||||
current_base = current_db ? (unsigned char*) current_db->ms
|
current_base = current_db ? (unsigned char*) current_db->ms
|
||||||
|
|||||||
@@ -54,7 +54,11 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
#include "ipc.h"
|
#include "ipc.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum DB_scope_mode {READER_SCOPE, WRITER_SCOPE};
|
||||||
|
|
||||||
class PgfDB {
|
class PgfDB {
|
||||||
private:
|
private:
|
||||||
@@ -62,10 +66,11 @@ private:
|
|||||||
const char *filepath;
|
const char *filepath;
|
||||||
malloc_state* ms;
|
malloc_state* ms;
|
||||||
|
|
||||||
ipc_rwlock_t *rwlock;
|
#ifndef _WIN32
|
||||||
|
pthread_rwlock_t *rwlock;
|
||||||
#ifdef _WIN32
|
#else
|
||||||
HANDLE hMap;
|
HANDLE hMap;
|
||||||
|
HANDLE hRWEvent;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
friend class PgfReader;
|
friend class PgfReader;
|
||||||
@@ -109,11 +114,12 @@ private:
|
|||||||
PGF_INTERNAL_DECL object malloc_internal(size_t bytes);
|
PGF_INTERNAL_DECL object malloc_internal(size_t bytes);
|
||||||
PGF_INTERNAL_DECL void free_internal(object o);
|
PGF_INTERNAL_DECL void free_internal(object o);
|
||||||
|
|
||||||
|
void lock(DB_scope_mode m);
|
||||||
|
void unlock();
|
||||||
|
|
||||||
friend class DB_scope;
|
friend class DB_scope;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum DB_scope_mode {READER_SCOPE, WRITER_SCOPE};
|
|
||||||
|
|
||||||
class PGF_INTERNAL_DECL DB_scope {
|
class PGF_INTERNAL_DECL DB_scope {
|
||||||
public:
|
public:
|
||||||
DB_scope(PgfDB *db, DB_scope_mode m);
|
DB_scope(PgfDB *db, DB_scope_mode m);
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
//#define DEBUG_IPC
|
//#define DEBUG_IPC
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
#ifdef DEBUG_IPC
|
#ifdef DEBUG_IPC
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#define PGF_INTERNAL static
|
#define PGF_INTERNAL static
|
||||||
|
|
||||||
void ipc_error() {
|
void ipc_error() {
|
||||||
perror(NULL);
|
perror(NULL);
|
||||||
exit(1);
|
exit(1);
|
||||||
@@ -20,7 +22,6 @@ void ipc_toomany() {
|
|||||||
#define ipc_toomany() throw pgf_error("Too many open grammars")
|
#define ipc_toomany() throw pgf_error("Too many open grammars")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef _WIN32
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@@ -107,8 +108,8 @@ next:
|
|||||||
}
|
}
|
||||||
|
|
||||||
PGF_INTERNAL
|
PGF_INTERNAL
|
||||||
ipc_rwlock_t *ipc_new_file_rwlock(const char* file_path,
|
pthread_rwlock_t *ipc_new_file_rwlock(const char* file_path,
|
||||||
bool *is_first)
|
bool *is_first)
|
||||||
{
|
{
|
||||||
if (file_path == NULL) {
|
if (file_path == NULL) {
|
||||||
*is_first = true;
|
*is_first = true;
|
||||||
@@ -258,7 +259,7 @@ ipc_rwlock_t *ipc_new_file_rwlock(const char* file_path,
|
|||||||
|
|
||||||
PGF_INTERNAL
|
PGF_INTERNAL
|
||||||
void ipc_release_file_rwlock(const char* file_path,
|
void ipc_release_file_rwlock(const char* file_path,
|
||||||
ipc_rwlock_t *rwlock)
|
pthread_rwlock_t *rwlock)
|
||||||
{
|
{
|
||||||
if (file_path == NULL) {
|
if (file_path == NULL) {
|
||||||
pthread_rwlock_destroy(rwlock);
|
pthread_rwlock_destroy(rwlock);
|
||||||
@@ -322,38 +323,6 @@ void ipc_release_file_rwlock(const char* file_path,
|
|||||||
|
|
||||||
pthread_mutex_unlock(&locks->mutex);
|
pthread_mutex_unlock(&locks->mutex);
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
PGF_INTERNAL
|
|
||||||
int ipc_rwlock_rdlock(ipc_rwlock_t *rwlock)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
PGF_INTERNAL
|
|
||||||
int ipc_rwlock_wrlock(ipc_rwlock_t *rwlock)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
PGF_INTERNAL
|
|
||||||
int ipc_rwlock_unlock(ipc_rwlock_t *rwlock)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
PGF_INTERNAL
|
|
||||||
ipc_rwlock_t *ipc_new_file_rwlock(const char* file_path,
|
|
||||||
bool *is_first)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
PGF_INTERNAL
|
|
||||||
void ipc_release_file_rwlock(const char* file_path,
|
|
||||||
ipc_rwlock_t *rwlock)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef DEBUG_IPC
|
#ifdef DEBUG_IPC
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
@@ -364,12 +333,13 @@ int main(int argc, char *argv[])
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_rwlock_t *rwlock = ipc_new_file_rwlock(argv[2]);
|
bool is_first;
|
||||||
|
ipc_rwlock_t *rwlock = ipc_new_file_rwlock(argv[2], &is_first);
|
||||||
|
|
||||||
if (strcmp(argv[1],"r") == 0) {
|
if (strcmp(argv[1],"r") == 0) {
|
||||||
pthread_rwlock_rdlock(rwlock);
|
ipc_rwlock_rdlock(rwlock);
|
||||||
} else if (strcmp(argv[1],"w") == 0) {
|
} else if (strcmp(argv[1],"w") == 0) {
|
||||||
pthread_rwlock_wrlock(rwlock);
|
ipc_rwlock_wrlock(rwlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
fputs("> ", stdout);
|
fputs("> ", stdout);
|
||||||
@@ -378,10 +348,11 @@ int main(int argc, char *argv[])
|
|||||||
char buf[16];
|
char buf[16];
|
||||||
read(0, buf, sizeof(buf));
|
read(0, buf, sizeof(buf));
|
||||||
|
|
||||||
pthread_rwlock_unlock(rwlock);
|
ipc_rwlock_unlock(rwlock);
|
||||||
|
|
||||||
ipc_release_file_rwlock(argv[2], rwlock);
|
ipc_release_file_rwlock(argv[2], rwlock);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -2,23 +2,12 @@
|
|||||||
#define IPC_H
|
#define IPC_H
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
#define ipc_rwlock_t pthread_rwlock_t
|
|
||||||
#define ipc_rwlock_rdlock pthread_rwlock_rdlock
|
|
||||||
#define ipc_rwlock_wrlock pthread_rwlock_wrlock
|
|
||||||
#define ipc_rwlock_unlock pthread_rwlock_unlock
|
|
||||||
#else
|
|
||||||
typedef struct ipc_rwlock_t ipc_rwlock_t;
|
|
||||||
int ipc_rwlock_rdlock(ipc_rwlock_t *rwlock);
|
|
||||||
int ipc_rwlock_wrlock(ipc_rwlock_t *rwlock);
|
|
||||||
int ipc_rwlock_unlock(ipc_rwlock_t *rwlock);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
PGF_INTERNAL_DECL
|
PGF_INTERNAL_DECL
|
||||||
ipc_rwlock_t *ipc_new_file_rwlock(const char* file_path,
|
pthread_rwlock_t *ipc_new_file_rwlock(const char* file_path,
|
||||||
bool *is_first);
|
bool *is_first);
|
||||||
|
|
||||||
PGF_INTERNAL_DECL
|
PGF_INTERNAL_DECL
|
||||||
void ipc_release_file_rwlock(const char* file_path,
|
void ipc_release_file_rwlock(const char* file_path,
|
||||||
ipc_rwlock_t *rwlock);
|
pthread_rwlock_t *rwlock);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user