Wrap table accesses in locks, should be good for dicts, field assignments?

This commit is contained in:
K. Lange 2021-02-10 18:19:10 +09:00
parent f9cfa4e622
commit 09ce6c46a9
6 changed files with 62 additions and 28 deletions

View File

@ -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; \

View File

@ -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;
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;

View File

@ -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
View 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

View File

@ -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

View File

@ -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)