Wrap table accesses in locks, should be good for dicts, field assignments?
This commit is contained in:
parent
f9cfa4e622
commit
09ce6c46a9
@ -3,6 +3,7 @@
|
||||
#include "value.h"
|
||||
#include "memory.h"
|
||||
#include "util.h"
|
||||
#include "threads.h"
|
||||
|
||||
#define LIST_WRAP_INDEX() \
|
||||
if (index < 0) index += self->values.count; \
|
||||
|
30
src/table.c
30
src/table.c
@ -6,6 +6,7 @@
|
||||
#include "memory.h"
|
||||
#include "table.h"
|
||||
#include "vm.h"
|
||||
#include "threads.h"
|
||||
|
||||
#define TABLE_MAX_LOAD 0.75
|
||||
|
||||
@ -13,6 +14,7 @@ void krk_initTable(KrkTable * table) {
|
||||
table->count = 0;
|
||||
table->capacity = 0;
|
||||
table->entries = NULL;
|
||||
pthread_rwlock_init(&table->lock, NULL);
|
||||
}
|
||||
|
||||
void krk_freeTable(KrkTable * table) {
|
||||
@ -82,6 +84,7 @@ static void adjustCapacity(KrkTable * table, size_t capacity) {
|
||||
}
|
||||
|
||||
int krk_tableSet(KrkTable * table, KrkValue key, KrkValue value) {
|
||||
pthread_rwlock_wrlock(&table->lock);
|
||||
if (table->count + 1 > table->capacity * TABLE_MAX_LOAD) {
|
||||
size_t capacity = GROW_CAPACITY(table->capacity);
|
||||
adjustCapacity(table, capacity);
|
||||
@ -91,6 +94,7 @@ int krk_tableSet(KrkTable * table, KrkValue key, KrkValue value) {
|
||||
if (isNewKey && IS_NONE(entry->value)) table->count++;
|
||||
entry->key = key;
|
||||
entry->value = value;
|
||||
pthread_rwlock_unlock(&table->lock);
|
||||
return isNewKey;
|
||||
}
|
||||
|
||||
@ -105,32 +109,48 @@ void krk_tableAddAll(KrkTable * from, KrkTable * to) {
|
||||
|
||||
int krk_tableGet(KrkTable * table, KrkValue key, KrkValue * value) {
|
||||
if (table->count == 0) return 0;
|
||||
pthread_rwlock_rdlock(&table->lock);
|
||||
KrkTableEntry * entry = krk_findEntry(table->entries, table->capacity, key);
|
||||
if (entry->key.type == VAL_KWARGS) return 0;
|
||||
*value = entry->value;
|
||||
return 1;
|
||||
if (entry->key.type == VAL_KWARGS) {
|
||||
pthread_rwlock_unlock(&table->lock);
|
||||
return 0;
|
||||
} else {
|
||||
*value = entry->value;
|
||||
pthread_rwlock_unlock(&table->lock);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int krk_tableDelete(KrkTable * table, KrkValue key) {
|
||||
if (table->count == 0) return 0;
|
||||
pthread_rwlock_rdlock(&table->lock);
|
||||
KrkTableEntry * entry = krk_findEntry(table->entries, table->capacity, key);
|
||||
if (entry->key.type == VAL_KWARGS) return 0;
|
||||
if (entry->key.type == VAL_KWARGS) {
|
||||
pthread_rwlock_unlock(&table->lock);
|
||||
return 0;
|
||||
}
|
||||
entry->key = KWARGS_VAL(0);
|
||||
entry->value = BOOLEAN_VAL(1);
|
||||
pthread_rwlock_unlock(&table->lock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
KrkString * krk_tableFindString(KrkTable * table, const char * chars, size_t length, uint32_t hash) {
|
||||
if (table->count == 0) return NULL;
|
||||
|
||||
pthread_rwlock_rdlock(&table->lock);
|
||||
uint32_t index = hash % table->capacity;
|
||||
for (;;) {
|
||||
KrkTableEntry * entry = &table->entries[index];
|
||||
if (entry->key.type == VAL_KWARGS) {
|
||||
if (IS_NONE(entry->value)) return NULL;
|
||||
if (IS_NONE(entry->value)) {
|
||||
pthread_rwlock_unlock(&table->lock);
|
||||
return NULL;
|
||||
}
|
||||
} else if (AS_STRING(entry->key)->length == length &&
|
||||
AS_STRING(entry->key)->hash == hash &&
|
||||
memcmp(AS_STRING(entry->key)->chars, chars, length) == 0) {
|
||||
pthread_rwlock_unlock(&table->lock);
|
||||
return AS_STRING(entry->key);
|
||||
}
|
||||
index = (index + 1) % table->capacity;
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <stdlib.h>
|
||||
#include "kuroko.h"
|
||||
#include "value.h"
|
||||
#include "threads.h"
|
||||
|
||||
typedef struct {
|
||||
KrkValue key;
|
||||
@ -20,6 +21,7 @@ typedef struct {
|
||||
size_t count;
|
||||
size_t capacity;
|
||||
KrkTableEntry * entries;
|
||||
pthread_rwlock_t lock;
|
||||
} KrkTable;
|
||||
|
||||
extern void krk_initTable(KrkTable * table);
|
||||
|
30
src/threads.h
Normal file
30
src/threads.h
Normal file
@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef ENABLE_THREADING
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
static inline void _krk_internal_spin_lock(int volatile * lock) {
|
||||
while(__sync_lock_test_and_set(lock, 0x01)) {
|
||||
sched_yield();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void _krk_internal_spin_unlock(int volatile * lock) {
|
||||
__sync_lock_release(lock);
|
||||
}
|
||||
|
||||
#define _obtain_lock(v) _krk_internal_spin_lock(&v);
|
||||
#define _release_lock(v) _krk_internal_spin_unlock(&v);
|
||||
|
||||
#else
|
||||
|
||||
#define _obtain_lock(v)
|
||||
#define _release_lock(v)
|
||||
|
||||
#define pthread_rwlock_init(a,b)
|
||||
#define pthread_rwlock_wrlock(a)
|
||||
#define pthread_rwlock_rdlock(a)
|
||||
#define pthread_rwlock_unlock(a)
|
||||
|
||||
#endif
|
||||
|
23
src/vm.h
23
src/vm.h
@ -234,27 +234,4 @@ extern int krk_doRecursiveModuleLoad(KrkString * name);
|
||||
extern KrkValue krk_operator_lt(KrkValue,KrkValue);
|
||||
extern KrkValue krk_operator_gt(KrkValue,KrkValue);
|
||||
|
||||
#ifdef ENABLE_THREADING
|
||||
#include <sched.h>
|
||||
static inline void _krk_internal_spin_lock(int volatile * lock) {
|
||||
while(__sync_lock_test_and_set(lock, 0x01)) {
|
||||
sched_yield();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void _krk_internal_spin_unlock(int volatile * lock) {
|
||||
__sync_lock_release(lock);
|
||||
}
|
||||
|
||||
#define _obtain_lock(v) _krk_internal_spin_lock(&v);
|
||||
#define _release_lock(v) _krk_internal_spin_unlock(&v);
|
||||
#else
|
||||
#define _obtain_lock(v)
|
||||
#define _release_lock(v)
|
||||
|
||||
#define pthread_rwlock_init(a,b)
|
||||
#define pthread_rwlock_wrlock(a)
|
||||
#define pthread_rwlock_rdlock(a)
|
||||
#define pthread_rwlock_unlock(a)
|
||||
#endif
|
||||
|
||||
|
@ -10,6 +10,7 @@ from fileio import open, stdin
|
||||
from threading import Thread
|
||||
|
||||
let l = []
|
||||
let d = {}
|
||||
let stop = False
|
||||
|
||||
class Racer(Thread):
|
||||
@ -22,6 +23,7 @@ class Racer(Thread):
|
||||
l.append('test')
|
||||
else if l:
|
||||
l[choice % len(l)] += choice
|
||||
d[choice] = str(choice)
|
||||
|
||||
let racers = [Racer() for i in range(5)]
|
||||
|
||||
@ -38,3 +40,5 @@ for racer in racers:
|
||||
racer.join()
|
||||
print("Here's l:")
|
||||
print(l)
|
||||
print("Here's d:")
|
||||
print(d)
|
||||
|
Loading…
Reference in New Issue
Block a user