// // Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo // // The contents of this file are covered under the licence agreement in the // file "LICENCE" distributed with Cforall. // // bits/containers.hfa -- Intrusive generic containers.hfa // // Author : Thierry Delisle // Created On : Tue Oct 31 16:38:50 2017 // Last Modified By : -- // Last Modified On : -- // Update Count : 0 #pragma once #include "bits/align.hfa" #include "bits/defs.hfa" //----------------------------------------------------------------------------- // Array //----------------------------------------------------------------------------- #ifdef __cforall forall(dtype T) #else #define T void #endif struct __small_array { T * data; __lock_size_t size; }; #undef T #ifdef __cforall #define __small_array_t(T) __small_array(T) #else #define __small_array_t(T) struct __small_array #endif #ifdef __cforall // forall(otype T | sized(T)) // static inline void ?{}(__small_array(T) & this) {} forall(dtype T | sized(T)) static inline T& ?[?]( __small_array(T) & this, __lock_size_t idx) { return ((typeof(this.data))this.data)[idx]; } forall(dtype T | sized(T)) static inline T& ?[?]( const __small_array(T) & this, __lock_size_t idx) { return ((typeof(this.data))this.data)[idx]; } forall(dtype T | sized(T)) static inline T* begin( const __small_array(T) & this ) { return ((typeof(this.data))this.data); } forall(dtype T | sized(T)) static inline T* end( const __small_array(T) & this ) { return ((typeof(this.data))this.data) + this.size; } #endif //----------------------------------------------------------------------------- // Node Base //----------------------------------------------------------------------------- #ifdef __cforall trait is_node(dtype T) { T*& get_next( T& ); }; #endif //----------------------------------------------------------------------------- // Stack //----------------------------------------------------------------------------- #ifdef __cforall forall(dtype TYPE | is_node(TYPE)) #define T TYPE #else #define T void #endif struct __stack { T * top; }; #undef T #ifdef __cforall #define __stack_t(T) __stack(T) #else #define __stack_t(T) struct __stack #endif #ifdef __cforall forall(dtype T | is_node(T)) static inline void ?{}( __stack(T) & this ) { (this.top){ NULL }; } forall(dtype T | is_node(T) | sized(T)) static inline void push( __stack(T) & this, T * val ) { verify( !get_next( *val ) ); get_next( *val ) = this.top; this.top = val; } forall(dtype T | is_node(T) | sized(T)) static inline T * pop( __stack(T) & this ) { T * top = this.top; if( top ) { this.top = get_next( *top ); get_next( *top ) = NULL; } return top; } #endif //----------------------------------------------------------------------------- // Queue //----------------------------------------------------------------------------- #ifdef __cforall forall(dtype TYPE | is_node(TYPE)) #define T TYPE #else #define T void #endif struct __queue { T * head; T ** tail; }; #undef T #ifdef __cforall #define __queue_t(T) __queue(T) #else #define __queue_t(T) struct __queue #endif #ifdef __cforall forall(dtype T | is_node(T)) static inline void ?{}( __queue(T) & this ) with( this ) { head{ NULL }; tail{ &head }; } forall(dtype T | is_node(T) | sized(T)) static inline void append( __queue(T) & this, T * val ) with( this ) { verify(tail != NULL); *tail = val; tail = &get_next( *val ); } forall(dtype T | is_node(T) | sized(T)) static inline T * pop_head( __queue(T) & this ) { T * head = this.head; if( head ) { this.head = get_next( *head ); if( !get_next( *head ) ) { this.tail = &this.head; } get_next( *head ) = NULL; } return head; } forall(dtype T | is_node(T) | sized(T)) static inline T * remove( __queue(T) & this, T ** it ) with( this ) { T * val = *it; verify( val ); (*it) = get_next( *val ); if( tail == &get_next( *val ) ) { tail = it; } get_next( *val ) = NULL; verify( (head == NULL) == (&head == tail) ); verify( *tail == NULL ); return val; } forall(dtype T | is_node(T)) static inline bool ?!=?( __queue(T) & this, __attribute__((unused)) zero_t zero ) { return this.head != 0; } #endif //----------------------------------------------------------------------------- // Doubly Linked List //----------------------------------------------------------------------------- #ifdef __cforall forall(dtype TYPE) #define T TYPE #define __getter_t * [T * & next, T * & prev] ( T & ) #else typedef void (*__generit_c_getter_t)(); #define T void #define __getter_t __generit_c_getter_t #endif struct __dllist { T * head; __getter_t __get; }; #undef T #undef __getter_t #ifdef __cforall #define __dllist_t(T) __dllist(T) #else #define __dllist_t(T) struct __dllist #endif #ifdef __cforall forall(dtype T | sized(T)) static inline [void] ?{}( __dllist(T) & this, * [T * & next, T * & prev] ( T & ) __get ) { this.head{ NULL }; this.__get = __get; } #define next 0 #define prev 1 forall(dtype T | sized(T)) static inline void push_front( __dllist(T) & this, T & node ) with( this ) { verify(__get); if ( head ) { __get( node ).next = head; __get( node ).prev = __get( *head ).prev; // inserted node must be consistent before it is seen // prevent code movement across barrier asm( "" : : : "memory" ); __get( *head ).prev = &node; T & _prev = *__get( node ).prev; __get( _prev ).next = &node; } else { __get( node ).next = &node; __get( node ).prev = &node; } // prevent code movement across barrier asm( "" : : : "memory" ); head = &node; } forall(dtype T | sized(T)) static inline void remove( __dllist(T) & this, T & node ) with( this ) { verify(__get); if ( &node == head ) { if ( __get( *head ).next == head ) { head = NULL; } else { head = __get( *head ).next; } } __get( *__get( node ).next ).prev = __get( node ).prev; __get( *__get( node ).prev ).next = __get( node ).next; __get( node ).next = NULL; __get( node ).prev = NULL; } forall(dtype T | sized(T)) static inline bool ?!=?( __dllist(T) & this, __attribute__((unused)) zero_t zero ) { return this.head != 0; } #undef next #undef prev #endif //----------------------------------------------------------------------------- // Tools //----------------------------------------------------------------------------- #ifdef __cforall #endif