Wrap some things in readers-writer locks and now more stuff doesn't break
This commit is contained in:
parent
345b021936
commit
43d1e86a2a
@ -39,6 +39,7 @@ KrkValue krk_list_of(int argc, KrkValue argv[]) {
|
||||
AS_LIST(outList)->count = argc;
|
||||
}
|
||||
|
||||
pthread_rwlock_init(&((KrkList*)AS_OBJECT(outList))->rwlock, NULL);
|
||||
return krk_pop();
|
||||
}
|
||||
|
||||
@ -48,25 +49,33 @@ KrkValue krk_list_of(int argc, KrkValue argv[]) {
|
||||
KRK_METHOD(list,__get__,{
|
||||
METHOD_TAKES_EXACTLY(1);
|
||||
CHECK_ARG(1,int,krk_integer_type,index);
|
||||
pthread_rwlock_rdlock(&self->rwlock);
|
||||
LIST_WRAP_INDEX();
|
||||
return self->values.values[index];
|
||||
KrkValue result = self->values.values[index];
|
||||
pthread_rwlock_unlock(&self->rwlock);
|
||||
return result;
|
||||
})
|
||||
|
||||
KRK_METHOD(list,__set__,{
|
||||
METHOD_TAKES_EXACTLY(2);
|
||||
CHECK_ARG(1,int,krk_integer_type,index);
|
||||
pthread_rwlock_rdlock(&self->rwlock);
|
||||
LIST_WRAP_INDEX();
|
||||
self->values.values[index] = argv[2];
|
||||
pthread_rwlock_unlock(&self->rwlock);
|
||||
})
|
||||
|
||||
KRK_METHOD(list,append,{
|
||||
METHOD_TAKES_EXACTLY(1);
|
||||
pthread_rwlock_wrlock(&self->rwlock);
|
||||
krk_writeValueArray(&self->values, argv[1]);
|
||||
pthread_rwlock_unlock(&self->rwlock);
|
||||
})
|
||||
|
||||
KRK_METHOD(list,insert,{
|
||||
METHOD_TAKES_EXACTLY(2);
|
||||
CHECK_ARG(1,int,krk_integer_type,index);
|
||||
pthread_rwlock_wrlock(&self->rwlock);
|
||||
LIST_WRAP_INDEX();
|
||||
krk_writeValueArray(&self->values, NONE_VAL());
|
||||
memmove(
|
||||
@ -75,6 +84,7 @@ KRK_METHOD(list,insert,{
|
||||
sizeof(KrkValue) * (self->values.count - index - 1)
|
||||
);
|
||||
self->values.values[index] = argv[2];
|
||||
pthread_rwlock_unlock(&self->rwlock);
|
||||
})
|
||||
|
||||
KRK_METHOD(list,__repr__,{
|
||||
@ -83,6 +93,7 @@ KRK_METHOD(list,__repr__,{
|
||||
((KrkObj*)self)->inRepr = 1;
|
||||
struct StringBuilder sb = {0};
|
||||
pushStringBuilder(&sb, '[');
|
||||
pthread_rwlock_rdlock(&self->rwlock);
|
||||
for (size_t i = 0; i < self->values.count; ++i) {
|
||||
/* repr(self[i]) */
|
||||
KrkClass * type = krk_getType(self->values.values[i]);
|
||||
@ -97,6 +108,7 @@ KRK_METHOD(list,__repr__,{
|
||||
pushStringBuilderStr(&sb, ", ", 2);
|
||||
}
|
||||
}
|
||||
pthread_rwlock_unlock(&self->rwlock);
|
||||
|
||||
pushStringBuilder(&sb,']');
|
||||
((KrkObj*)self)->inRepr = 0;
|
||||
@ -116,6 +128,7 @@ KRK_METHOD(list,__repr__,{
|
||||
} while (0)
|
||||
KRK_METHOD(list,extend,{
|
||||
METHOD_TAKES_EXACTLY(1);
|
||||
pthread_rwlock_wrlock(&self->rwlock);
|
||||
KrkValueArray * positionals = AS_LIST(argv[0]);
|
||||
KrkValue value = argv[1];
|
||||
if (IS_TUPLE(value)) {
|
||||
@ -148,15 +161,18 @@ KRK_METHOD(list,extend,{
|
||||
krk_pop();
|
||||
} while (1);
|
||||
} else {
|
||||
pthread_rwlock_unlock(&self->rwlock);
|
||||
return krk_runtimeError(vm.exceptions->typeError, "'%s' object is not iterable", krk_typeName(value));
|
||||
}
|
||||
}
|
||||
pthread_rwlock_unlock(&self->rwlock);
|
||||
})
|
||||
#undef unpackArray
|
||||
|
||||
KRK_METHOD(list,__init__,{
|
||||
METHOD_TAKES_AT_MOST(1);
|
||||
krk_initValueArray(AS_LIST(argv[0]));
|
||||
pthread_rwlock_init(&self->rwlock, NULL);
|
||||
if (argc == 2) {
|
||||
_list_extend(2,(KrkValue[]){argv[0],argv[1]},0);
|
||||
}
|
||||
@ -185,9 +201,14 @@ KRK_METHOD(list,__len__,{
|
||||
|
||||
KRK_METHOD(list,__contains__,{
|
||||
METHOD_TAKES_EXACTLY(1);
|
||||
pthread_rwlock_rdlock(&self->rwlock);
|
||||
for (size_t i = 0; i < self->values.count; ++i) {
|
||||
if (krk_valuesEqual(argv[1], self->values.values[i])) return BOOLEAN_VAL(1);
|
||||
if (krk_valuesEqual(argv[1], self->values.values[i])) {
|
||||
pthread_rwlock_unlock(&self->rwlock);
|
||||
return BOOLEAN_VAL(1);
|
||||
}
|
||||
}
|
||||
pthread_rwlock_unlock(&self->rwlock);
|
||||
return BOOLEAN_VAL(0);
|
||||
})
|
||||
|
||||
@ -195,6 +216,7 @@ KRK_METHOD(list,__getslice__,{
|
||||
METHOD_TAKES_EXACTLY(2);
|
||||
if (!(IS_INTEGER(argv[1]) || IS_NONE(argv[1]))) return TYPE_ERROR(int or None, argv[1]);
|
||||
if (!(IS_INTEGER(argv[2]) || IS_NONE(argv[2]))) return TYPE_ERROR(int or None, argv[2]);
|
||||
pthread_rwlock_rdlock(&self->rwlock);
|
||||
krk_integer_type start = IS_NONE(argv[1]) ? 0 : AS_INTEGER(argv[1]);
|
||||
krk_integer_type end = IS_NONE(argv[2]) ? (krk_integer_type)self->values.count : AS_INTEGER(argv[2]);
|
||||
LIST_WRAP_SOFT(start);
|
||||
@ -202,7 +224,9 @@ KRK_METHOD(list,__getslice__,{
|
||||
if (end < start) end = start;
|
||||
krk_integer_type len = end - start;
|
||||
|
||||
return krk_list_of(len, &AS_LIST(argv[0])->values[start]);
|
||||
KrkValue result = krk_list_of(len, &AS_LIST(argv[0])->values[start]);
|
||||
pthread_rwlock_unlock(&self->rwlock);
|
||||
return result;
|
||||
})
|
||||
|
||||
FUNC_SIG(list,pop);
|
||||
@ -210,6 +234,7 @@ KRK_METHOD(list,__delslice__,{
|
||||
METHOD_TAKES_EXACTLY(2);
|
||||
if (!(IS_INTEGER(argv[1]) || IS_NONE(argv[1]))) return TYPE_ERROR(int or None, argv[1]);
|
||||
if (!(IS_INTEGER(argv[2]) || IS_NONE(argv[2]))) return TYPE_ERROR(int or None, argv[2]);
|
||||
pthread_rwlock_wrlock(&self->rwlock);
|
||||
krk_integer_type start = IS_NONE(argv[1]) ? 0 : AS_INTEGER(argv[1]);
|
||||
krk_integer_type end = IS_NONE(argv[2]) ? (krk_integer_type)self->values.count : AS_INTEGER(argv[2]);
|
||||
LIST_WRAP_SOFT(start);
|
||||
@ -221,6 +246,7 @@ KRK_METHOD(list,__delslice__,{
|
||||
FUNC_NAME(list,pop)(2,(KrkValue[]){argv[0],INTEGER_VAL(start)},0);
|
||||
len--;
|
||||
}
|
||||
pthread_rwlock_unlock(&self->rwlock);
|
||||
})
|
||||
|
||||
KRK_METHOD(list,__setslice__,{
|
||||
@ -228,6 +254,7 @@ KRK_METHOD(list,__setslice__,{
|
||||
if (!(IS_INTEGER(argv[1]) || IS_NONE(argv[1]))) return TYPE_ERROR(int or None, argv[1]);
|
||||
if (!(IS_INTEGER(argv[2]) || IS_NONE(argv[2]))) return TYPE_ERROR(int or None, argv[2]);
|
||||
if (!IS_list(argv[3])) return TYPE_ERROR(list,argv[3]); /* TODO other sequence types */
|
||||
pthread_rwlock_wrlock(&self->rwlock);
|
||||
krk_integer_type start = IS_NONE(argv[1]) ? 0 : AS_INTEGER(argv[1]);
|
||||
krk_integer_type end = IS_NONE(argv[2]) ? (krk_integer_type)self->values.count : AS_INTEGER(argv[2]);
|
||||
LIST_WRAP_SOFT(start);
|
||||
@ -251,10 +278,12 @@ KRK_METHOD(list,__setslice__,{
|
||||
len--;
|
||||
}
|
||||
|
||||
pthread_rwlock_unlock(&self->rwlock);
|
||||
})
|
||||
|
||||
KRK_METHOD(list,pop,{
|
||||
METHOD_TAKES_AT_MOST(1);
|
||||
pthread_rwlock_wrlock(&self->rwlock);
|
||||
krk_integer_type index = self->values.count - 1;
|
||||
if (argc == 2) {
|
||||
CHECK_ARG(1,int,krk_integer_type,ind);
|
||||
@ -264,6 +293,7 @@ KRK_METHOD(list,pop,{
|
||||
KrkValue outItem = AS_LIST(argv[0])->values[index];
|
||||
if (index == (long)AS_LIST(argv[0])->count-1) {
|
||||
AS_LIST(argv[0])->count--;
|
||||
pthread_rwlock_unlock(&self->rwlock);
|
||||
return outItem;
|
||||
} else {
|
||||
/* Need to move up */
|
||||
@ -271,23 +301,29 @@ KRK_METHOD(list,pop,{
|
||||
memmove(&AS_LIST(argv[0])->values[index], &AS_LIST(argv[0])->values[index+1],
|
||||
sizeof(KrkValue) * remaining);
|
||||
AS_LIST(argv[0])->count--;
|
||||
pthread_rwlock_unlock(&self->rwlock);
|
||||
return outItem;
|
||||
}
|
||||
})
|
||||
|
||||
KRK_METHOD(list,remove,{
|
||||
METHOD_TAKES_EXACTLY(1);
|
||||
pthread_rwlock_wrlock(&self->rwlock);
|
||||
for (size_t i = 0; i < self->values.count; ++i) {
|
||||
if (krk_valuesEqual(self->values.values[i], argv[1])) {
|
||||
pthread_rwlock_unlock(&self->rwlock);
|
||||
return FUNC_NAME(list,pop)(2,(KrkValue[]){argv[0], INTEGER_VAL(i)},0);
|
||||
}
|
||||
}
|
||||
pthread_rwlock_unlock(&self->rwlock);
|
||||
return krk_runtimeError(vm.exceptions->valueError, "not found");
|
||||
})
|
||||
|
||||
KRK_METHOD(list,clear,{
|
||||
METHOD_TAKES_NONE();
|
||||
pthread_rwlock_wrlock(&self->rwlock);
|
||||
krk_freeValueArray(&self->values);
|
||||
pthread_rwlock_unlock(&self->rwlock);
|
||||
})
|
||||
|
||||
KRK_METHOD(list,index,{
|
||||
@ -311,13 +347,18 @@ KRK_METHOD(list,index,{
|
||||
return krk_runtimeError(vm.exceptions->typeError, "max must be int, not '%s'", krk_typeName(argv[3]));
|
||||
}
|
||||
|
||||
pthread_rwlock_rdlock(&self->rwlock);
|
||||
LIST_WRAP_SOFT(min);
|
||||
LIST_WRAP_SOFT(max);
|
||||
|
||||
for (krk_integer_type i = min; i < max; ++i) {
|
||||
if (krk_valuesEqual(self->values.values[i], argv[1])) return INTEGER_VAL(i);
|
||||
if (krk_valuesEqual(self->values.values[i], argv[1])) {
|
||||
pthread_rwlock_unlock(&self->rwlock);
|
||||
return INTEGER_VAL(i);
|
||||
}
|
||||
}
|
||||
|
||||
pthread_rwlock_unlock(&self->rwlock);
|
||||
return krk_runtimeError(vm.exceptions->valueError, "not found");
|
||||
})
|
||||
|
||||
@ -325,25 +366,32 @@ KRK_METHOD(list,count,{
|
||||
METHOD_TAKES_EXACTLY(1);
|
||||
krk_integer_type count = 0;
|
||||
|
||||
pthread_rwlock_rdlock(&self->rwlock);
|
||||
for (size_t i = 0; i < self->values.count; ++i) {
|
||||
if (krk_valuesEqual(self->values.values[i], argv[1])) count++;
|
||||
}
|
||||
pthread_rwlock_unlock(&self->rwlock);
|
||||
|
||||
return INTEGER_VAL(count);
|
||||
})
|
||||
|
||||
KRK_METHOD(list,copy,{
|
||||
METHOD_TAKES_NONE();
|
||||
return krk_list_of(self->values.count, self->values.values);
|
||||
pthread_rwlock_rdlock(&self->rwlock);
|
||||
KrkValue result = krk_list_of(self->values.count, self->values.values);
|
||||
pthread_rwlock_unlock(&self->rwlock);
|
||||
return result;
|
||||
})
|
||||
|
||||
KRK_METHOD(list,reverse,{
|
||||
METHOD_TAKES_NONE();
|
||||
pthread_rwlock_wrlock(&self->rwlock);
|
||||
for (size_t i = 0; i < (self->values.count) / 2; i++) {
|
||||
KrkValue tmp = self->values.values[i];
|
||||
self->values.values[i] = self->values.values[self->values.count-i-1];
|
||||
self->values.values[self->values.count-i-1] = tmp;
|
||||
}
|
||||
pthread_rwlock_unlock(&self->rwlock);
|
||||
return NONE_VAL();
|
||||
})
|
||||
|
||||
@ -361,14 +409,18 @@ static int _list_sorter(const void * _a, const void * _b) {
|
||||
KRK_METHOD(list,sort,{
|
||||
METHOD_TAKES_NONE();
|
||||
|
||||
pthread_rwlock_wrlock(&self->rwlock);
|
||||
qsort(self->values.values, self->values.count, sizeof(KrkValue), _list_sorter);
|
||||
pthread_rwlock_unlock(&self->rwlock);
|
||||
})
|
||||
|
||||
KRK_METHOD(list,__add__,{
|
||||
METHOD_TAKES_EXACTLY(1);
|
||||
if (!IS_list(argv[1])) return TYPE_ERROR(list,argv[1]);
|
||||
|
||||
pthread_rwlock_rdlock(&self->rwlock);
|
||||
KrkValue outList = krk_list_of(self->values.count, self->values.values); /* copy */
|
||||
pthread_rwlock_unlock(&self->rwlock);
|
||||
FUNC_NAME(list,extend)(2,(KrkValue[]){outList,argv[1]},0); /* extend */
|
||||
return outList;
|
||||
})
|
||||
|
25
src/object.c
25
src/object.c
@ -11,13 +11,22 @@
|
||||
#define ALLOCATE_OBJECT(type, objectType) \
|
||||
(type*)allocateObject(sizeof(type), objectType)
|
||||
|
||||
#ifdef ENABLE_THREADING
|
||||
static volatile int _stringLock = 0;
|
||||
static volatile int _objectLock = 0;
|
||||
#endif
|
||||
|
||||
static KrkObj * allocateObject(size_t size, ObjType type) {
|
||||
KrkObj * object = (KrkObj*)krk_reallocate(NULL, 0, size);
|
||||
memset(object,0,size);
|
||||
object->type = type;
|
||||
|
||||
_obtain_lock(_objectLock);
|
||||
object->next = vm.objects;
|
||||
krk_currentThread.scratchSpace[2] = OBJECT_VAL(object);
|
||||
vm.objects = object;
|
||||
_release_lock(_objectLock);
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
@ -184,22 +193,32 @@ static uint32_t hashString(const char * key, size_t length) {
|
||||
|
||||
KrkString * krk_takeString(char * chars, size_t length) {
|
||||
uint32_t hash = hashString(chars, length);
|
||||
_obtain_lock(_stringLock);
|
||||
KrkString * interned = krk_tableFindString(&vm.strings, chars, length, hash);
|
||||
if (interned != NULL) {
|
||||
FREE_ARRAY(char, chars, length + 1);
|
||||
_release_lock(_stringLock);
|
||||
return interned;
|
||||
}
|
||||
return allocateString(chars, length, hash);
|
||||
KrkString * result = allocateString(chars, length, hash);
|
||||
_release_lock(_stringLock);
|
||||
return result;
|
||||
}
|
||||
|
||||
KrkString * krk_copyString(const char * chars, size_t length) {
|
||||
uint32_t hash = hashString(chars, length);
|
||||
_obtain_lock(_stringLock);
|
||||
KrkString * interned = krk_tableFindString(&vm.strings, chars, length, hash);
|
||||
if (interned) return interned;
|
||||
if (interned) {
|
||||
_release_lock(_stringLock);
|
||||
return interned;
|
||||
}
|
||||
char * heapChars = ALLOCATE(char, length + 1);
|
||||
memcpy(heapChars, chars, length);
|
||||
heapChars[length] = '\0';
|
||||
return allocateString(heapChars, length, hash);
|
||||
KrkString * result = allocateString(heapChars, length, hash);
|
||||
_release_lock(_stringLock);
|
||||
return result;
|
||||
}
|
||||
|
||||
KrkFunction * krk_newFunction(void) {
|
||||
|
@ -7,6 +7,10 @@
|
||||
#include "chunk.h"
|
||||
#include "table.h"
|
||||
|
||||
#ifdef ENABLE_THREADING
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#define OBJECT_TYPE(value) (AS_OBJECT(value)->type)
|
||||
#define IS_STRING(value) isObjType(value, OBJ_STRING)
|
||||
#define AS_STRING(value) ((KrkString *)AS_OBJECT(value))
|
||||
@ -188,6 +192,9 @@ typedef struct {
|
||||
typedef struct {
|
||||
KrkInstance inst;
|
||||
KrkValueArray values;
|
||||
#ifdef ENABLE_THREADING
|
||||
pthread_rwlock_t rwlock;
|
||||
#endif
|
||||
} KrkList;
|
||||
|
||||
typedef struct {
|
||||
|
5
src/vm.h
5
src/vm.h
@ -251,5 +251,10 @@ static inline void _krk_internal_spin_unlock(int volatile * lock) {
|
||||
#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
|
||||
|
||||
|
@ -16,17 +16,17 @@ class Racer(Thread):
|
||||
def run(self):
|
||||
let myRando = open('/dev/urandom','rb')
|
||||
while not stop:
|
||||
let choice = myRando.read(1)[0]
|
||||
if choice > 127:
|
||||
let bytes = myRando.read(4)
|
||||
let choice = (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | (bytes[3])
|
||||
if choice > 2147483647:
|
||||
l.append('test')
|
||||
else if l:
|
||||
l[choice % len(l)] += choice
|
||||
|
||||
let racerA = Racer()
|
||||
let racerB = Racer()
|
||||
let racers = [Racer() for i in range(5)]
|
||||
|
||||
racerA.start()
|
||||
racerB.start()
|
||||
for racer in racers:
|
||||
racer.start()
|
||||
|
||||
print("Press enter to stop.")
|
||||
stdin.readline()
|
||||
@ -34,7 +34,7 @@ stdin.readline()
|
||||
stop = True
|
||||
|
||||
print("Waiting for threads...")
|
||||
racerA.join()
|
||||
racerB.join()
|
||||
for racer in racers:
|
||||
racer.join()
|
||||
print("Here's l:")
|
||||
print(l)
|
||||
|
Loading…
Reference in New Issue
Block a user