#ifndef CYCLONE_CK_POLYFILL_H #define CYCLONE_CK_POLYFILL_H #include "cyclone/types.h" #include "cyclone/hashset.h" #include #include void ck_polyfill_init(); struct ck_malloc { void *(*malloc)(size_t); void *(*realloc)(void *, size_t, size_t, bool); void (*free)(void *, size_t, bool); }; /////////////////////////////////////////////////////////////////////////////// // Simple hashset (hashset with string support) /* hash function */ typedef size_t (*hash_func_t)(const char *, size_t); struct simple_hashset_item_st { size_t hash; symbol_type *item; }; struct simple_hashset_st { size_t nbits; size_t mask; size_t capacity; struct simple_hashset_item_st *items; size_t nitems; size_t n_deleted_items; hash_func_t hash_func; }; // struct simple_hashset_st; typedef struct simple_hashset_st *simple_hashset_t; struct hashmap_st; typedef struct hashmap_st *hashmap_t; /* * HASHSET FUNCTIONS */ /* create hashset instance */ simple_hashset_t simple_hashset_create(void); /* destroy hashset instance */ void simple_hashset_destroy(simple_hashset_t set); /* set hash function */ void simple_hashset_set_hash_function(simple_hashset_t set, hash_func_t func); /* add item into the hashset. * * @note 0 and 1 is special values, meaning nil and deleted items. the * function will return -1 indicating error. * * returns zero if the item already in the set and non-zero otherwise */ int simple_hashset_add(simple_hashset_t set, symbol_type * key); /* check if existence of the item * * returns non-zero if the item exists and zero otherwise */ int simple_hashset_is_member(simple_hashset_t set, symbol_type * key); static inline uint64_t MurmurHash64A(const void *key, int len, uint64_t seed) { return 0; } /////////////////////////////////////////////////////////////////////////////// // CK Hashset section #define CK_HS_MODE_OBJECT 0 #define CK_HS_MODE_SPMC 0 struct ck_hs { pthread_mutex_t lock; simple_hashset_t hs; }; typedef struct ck_hs ck_hs_t; /* * Hash callback function. */ typedef unsigned long ck_hs_hash_cb_t(const void *, unsigned long); /* * Returns pointer to object if objects are equivalent. */ typedef bool ck_hs_compare_cb_t(const void *, const void *); #define CK_HS_HASH(hs, hs_hash, value) 0 bool ck_hs_init(ck_hs_t *, unsigned int, ck_hs_hash_cb_t *, ck_hs_compare_cb_t *, struct ck_malloc *, unsigned long, unsigned long); void *ck_hs_get(ck_hs_t *, unsigned long, const void *); bool ck_hs_put(ck_hs_t *, unsigned long, const void *); /* struct ck_hs { struct ck_malloc *m; struct ck_hs_map *map; unsigned int mode; unsigned long seed; ck_hs_hash_cb_t *hf; ck_hs_compare_cb_t *compare; }; typedef struct ck_hs ck_hs_t; */ /////////////////////////////////////////////////////////////////////////////// // CK Array section struct ck_array { pthread_mutex_t lock; hashset_t hs; }; typedef struct ck_array ck_array_t; struct ck_array_iterator { int unused; }; typedef struct ck_array_iterator ck_array_iterator_t; #define CK_ARRAY_MODE_SPMC 0 // DESCRIPTION // The ck_array_init(3) function initializes the array pointed to by the // argument array. The mode value must be CK_ARRAY_MODE_SPMC. The // allocator argument must point to a ck_malloc data structure with valid // non-NULL function pointers initialized for malloc, free and realloc. The // initial_length specifies the initial length of the array. The value of // initial_length must be greater than or equal to 2. An array allows for // one concurrent put or remove operations in the presence of any number of // concurrent CK_ARRAY_FOREACH operations. // // RETURN VALUES // This function returns true if the array was successfully created. It // returns false if the creation failed. Failure may occur due to internal // memory allocation failures or invalid arguments. bool ck_array_init(ck_array_t * array, unsigned int mode, struct ck_malloc *allocator, unsigned int initial_length); // DESCRIPTION // The ck_array_put_unique(3) function will attempt to insert the value of // pointer into the array pointed to by array. This function may incur // additional memory allocations if not enough memory has been allocated in // the array for a new entry. The operation is also free to apply the opera- // tion immediately if there is an opportunity for elimination with a pend- // ing (uncommitted) remove operation. The function will not make any modi- // fications if the pointer already exists in the array. // // RETURN VALUES // This function returns 1 if the pointer already exists in the array. It // returns 0 if the put operation succeeded. It returns -1 on error due to // internal memory allocation failures. int ck_array_put_unique(ck_array_t * array, void *pointer); // DESCRIPTION // The ck_array_remove(3) function will attempt to remove the value of // pointer into the array pointed to by array. The operation is also free to // apply the operation immediately if there is an opportunity for elimina- // tion with a pending (uncommitted) put operation. If no elimination was // possible, the function may require to allocate more memory. // // RETURN VALUES // This function returns true if the remove operation succeeded. It will // return false otherwise due to internal allocation failures or because the // value did not exist. bool ck_array_remove(ck_array_t * array, void *pointer); // DESCRIPTION // The ck_array_commit(3) function will commit any pending put or remove // operations associated with the array. The function may end up requesting // the safe reclamation of memory actively being iterated upon by other // threads. // // RETURN VALUES // This function returns true if the commit operation succeeded. It will // return false otherwise, and pending operations will not be applied. bool ck_array_commit(ck_array_t * array); // TODO: // Can we safely lock the array, make a copy, and interate over that???? #define CK_ARRAY_FOREACH(a, i, b) \ pthread_mutex_lock(&((a)->lock)); \ int tmpc = (a)->hs->nitems; \ void **tmp = alloca(sizeof(void *) * tmpc); \ hashset_to_array((a)->hs, tmp); \ pthread_mutex_unlock(&((a)->lock)); \ if (tmpc > 0) { (*b) = tmp[0]; } \ for (unsigned int _ck_i = 0; \ _ck_i < tmpc; \ _ck_i++, (*b) = tmp[_ck_i]) /////////////////////////////////////////////////////////////////////////////// // CK PR section bool ck_pr_cas_ptr(void *target, void *old_value, void *new_value); bool ck_pr_cas_int(int *target, int old_value, int new_value); bool ck_pr_cas_8(uint8_t * target, uint8_t old_value, uint8_t new_value); void ck_pr_add_ptr(void *target, uintptr_t delta); void ck_pr_add_int(int *target, int delta); void ck_pr_add_8(uint8_t * target, uint8_t delta); void *ck_pr_load_ptr(const void *target); int ck_pr_load_int(const int *target); uint8_t ck_pr_load_8(const uint8_t * target); void ck_pr_store_ptr(void *target, void *value); #endif /* CYCLONE_CK_POLYFILL_H */