Recent Entries 10
- pattern minor 112d ago(Optionally Concurrent) FIFOBased on Concurrent FIFO in C++11 and my review I implemented a queue and its concurrent pendant. Is there anything left to improve regarding clarity, usability, code-style, lock-times or general efficiency? ``` #ifndef FIFO_H #define FIFO_H #include #include #include #include #include template class ST_FIFO { static_assert(CAPACITY, "Needs to have non-zero capacity"); T data[CAPACITY + 1]; std::size_t input_index = 0; std::size_t output_index = 0; inline static constexpr std::size_t wrap_index(std::size_t index) noexcept { return index > CAPACITY ? index - CAPACITY - 1 : index; } public: static constexpr std::size_t capacity() noexcept { return CAPACITY; } bool empty() const noexcept { return input_index == output_index; } std::size_t size() const noexcept { return input_index >= output_index ? input_index - output_index : input_index + CAPACITY + 1 - output_index; } template auto push(X&& x) noexcept(noexcept(pop(*data), *data = std::forward(x))) -> decltype(*data = std::forward(x), true) { if(size() == CAPACITY) pop(data[input_index]); data[input_index] = std::forward(x); input_index = wrap_index(input_index + 1); return true; } template auto try_push(X&& x) noexcept(noexcept(*data = std::forward(x))) -> decltype(*data = std::forward(x), true) { if(size() == CAPACITY) return false; data[input_index] = std::forward(x); input_index = wrap_index(input_index + 1); return true; } std::size_t multi_push(const T ts[], size_t count) noexcept(noexcept(push(*ts))) { for (size_t i = 0; i = size()) return false; t = data[wrap_index(output_index + ind)]; return true; } }; template class MT_FIFO : ST_FIFO { std::atomic_bool wait_flag = true; mutable std::mutex mutex; mutable std::condition_variabl
- pattern minor 112d agoConcurrent FIFO in C++11I have implemented a simple FIFO that can optionally be used by either a single thread or way to pass data between threads. The class is templated with arguments for the types the queue will contain and also the number of elements in the queue (queue data is stored in an `std::array`). For single thread use, it is instantiated by: ``` ST_FIFO ``` and for use in a multithreaded context: ``` MT_FIFO ``` It has these methods: - `push` (with and without move semantics): put one item one the buffer. Always succeeds--if buffer is full, oldest element is popped. - `try_push`: put one item into the buffer. If buffer is full, push fails. - `multi_push`: push a number of items onto buffer. Mostly useful for multi-threaded, where all items are pushed under same lock. Always succeeds. - `try_multi_push`: same as multi_push, but fails if buffer is full. - `pop`: pops one item off buffer. In single threaded version, returns immediately if buffer is empty. In multi-threaded version, this method blocks (using a condition variable) until data becomes available. - `multi_pop`: pops a given number of items out of the buffer. If buffer contains fewer items than number requested, returns all items in buffer. In multi-threaded version, blocks until one item becomes available. Returns number of items popped from buffer. - `peek`: get an item from buffer without removing it. Can be any item in the buffer, but must be less than the number of items in the buffer. - `size`: returns number of items in buffer. - `is_empty`: returns true if buffer is empty. Specifically for the multi-threaded version: - `try_pop`: pops an item from buffer. If buffer is empty returns false immediately. - `wait_off`: if a thread is waiting for an item to be popped, this method can be called from another thread to terminate the waiting (useful to unblock the thread when exiting. - `wait_on`: turns waiting back on. After making it I found this article and this article, which impleme
- pattern minor 112d agoStack and Queue Linked List ImplementationsI'm relatively new to C as a language, but I wouldn't call myself a beginner. That being said, I don't believe my C "coding style," so to speak, is particularly developed. Also, I'm new to error handling in C as well. stack.c ``` #include #include typedef struct node { int val; struct node* next; } node_t; typedef struct stack { struct node* head; } stack_t; stack_t* create_list(void) { stack_t* stack = malloc(sizeof *stack); if (stack != NULL) { stack->head = NULL; } return stack; } void push(stack_t* list, int val) { node_t* newnode = malloc(sizeof *newnode); if (newnode != NULL) { newnode->val = val; newnode->next = list->head; } list->head = newnode; } int pop(stack_t* list) { int val = list->head->val; node_t* next = list->head->next; free(list->head); list->head = next; return val; } void destroy_list(stack_t* list) { do { node_t* head = list->head; node_t* next = head->next; free(head); list->head = next; } while (list->head); free(list); } void foreach(stack_t* list, int (*func)(const int)) { node_t* curr = list->head; do { curr->val = func(curr->val); curr = curr->next; } while(curr); } int print_val(const int val) { printf("value: %d\n", val); return val; } int main(int argc, char* argv[]) { printf("creating list\n"); stack_t* list = create_list(); printf("pushing value 2\n"); push(list, 2); printf("top value: %d\n", list->head->val); printf("pushing value 5\n"); push(list, 5); printf("top value: %d\n", list->head->val); printf("iterating top-down\n"); foreach(list, print_val); printf("popping top value\n"); int popped = pop(list); printf("popped: %d\n", popped); printf("top value: %d\n", list->head->val); destroy_list(list); return 0; } ``` queue.c ``` #include #include type
- pattern minor 112d agoMax-Heap arraylist based priority queue written in JavaI have a program that I'm writing that needs to use a priority queue as part of an algorithm. I specifically need to order (String, Integer) pairs for example (Bread, 3), (Beer, 5), (Eggs,2), etc. I'd appreciate any comments on my code style and how I've written my class. ``` import javafx.util.Pair; import java.util.ArrayList; import java.util.Collections; public class FPPriorityQueue implements PriorityQueue { private ArrayList> heapArray; public FPPriorityQueue(){ super(); heapArray = new ArrayList>(); } public boolean empty(){ return true; } private Integer getParentData(int index){ int parentIndex = index/2; Pair parentData = heapArray.get(parentIndex); return parentData.getValue(); } private void swap(Integer old, Integer knew){ Collections.swap(heapArray,old,knew); } private void shiftUp(int index){ int parentIndex; if(index != 1){ parentIndex = index/2; int childData = heapArray.get(index).getValue(); int parentData = getParentData(index); if(parentData (index*2)+1) { int leftChildValue = heapArray.get(index * 2).getValue(); int rightChildValue = heapArray.get((index * 2) + 1).getValue(); int indexValue = heapArray.get(index).getValue(); if(indexValue rightChildValue){ int leftChildIndex = index*2; swap(index,leftChildIndex); shiftDown(leftChildIndex); } else{ int rightChildIndex = (index*2)+1; swap(index,rightChildIndex); shiftDown(rightChildIndex); } } } } public void insert(String key, Integer value){ Pair element = new Pair(key,value); Pair nullElement = new Pair("NULL",0); //add the element to the last position in the list if(heapArray.isEmpty()){ heapArray.add(0,nullElement); heapArray.add(1,element); } else{ heapArray.add(heapArray.size(), eleme
- pattern minor 112d agoLock-free FIFO queue implementation``` struct __fifo_node_t { void *next; }; typedef struct __fifo_node_t fifo_node_t; struct __fifo_list_t { void *next; void *tail; }; typedef struct __fifo_list_t fifo_list_t; static inline void __fifo_list_push(fifo_list_t *head, fifo_node_t *node) { fifo_node_t *prev; node->next = head; prev = atomic_xchg64(&head->tail, node); prev->next = node; } static inline fifo_node_t *__fifo_list_pop(fifo_list_t *head) { fifo_node_t *node; while ((node = ACCESS_ONCE(head->next)) != head) { fifo_node_t *next = ACCESS_ONCE(node->next); if (cmpxchg_eq(&head->next, node, next) == node) { if (cmpxchg_eq(&head->tail, node, head) != node && next == head) while (ACCESS_ONCE(head->next) == next) head->next = ACCESS_ONCE(node->next); return node; } } return NULL; } static inline void __fifo_list_init(fifo_list_t *head) { head->next = head->tail = head; } ``` `atomic_xchg64` - Atomic exchange 64bit with new value and return the old value `cmpxchg_eq` - Atomic compare and exchange 64bit with new value and return the old value `ACCESS_ONCE` - `(*(volatile typeof(x) *)&(x))` Can you review it? Is this implementation thread-safe ? Thank you.
- pattern minor 112d agoLinked deque implementation in CI wrote a deque implementation in C for storing `char *`. It uses a doubly linked list, but I'm calling it a deque since it can only push/pop from the head and tail of the list. I don't have much experience writing C (I'm more of a Python guy) so please let me know what can be improved! I am already aware of the following: - there are no comments (I've tried to use self-explanatory names) - the testing isn't particularly rigorous linkedlist.h ``` #ifndef _LINKEDLIST_H #define _LINKEDLIST_H #include struct ll_node { struct ll_node *prev; struct ll_node *next; char *data; }; struct linkedlist { struct ll_node *head; struct ll_node *tail; size_t length; }; void ll_node_init(struct ll_node *node, char *data); void ll_init(struct linkedlist *ll); void ll_destroy(struct linkedlist *ll); void ll_push_head(struct linkedlist *ll, char *data); void ll_push_tail(struct linkedlist *ll, char *data); char *ll_pop_head(struct linkedlist *ll); char *ll_pop_tail(struct linkedlist *ll); #endif ``` linkedlist.c ``` #include #include "linkedlist.h" void ll_node_init(struct ll_node *node, char *data) { node->prev = NULL; node->next = NULL; node->data = data; } void ll_init(struct linkedlist *ll) { ll->head = NULL; ll->tail = NULL; ll->length = 0; } void ll_destroy(struct linkedlist *ll) { struct ll_node *node = ll->head; struct ll_node *next; while(node != NULL) { next = node->next; free(node); node = next; } } void ll_push_head(struct linkedlist *ll, char *data) { struct ll_node *node = malloc(sizeof(struct ll_node)); ll_node_init(node, data); if(ll->head != NULL) { ll->head->prev = node; } if(ll->tail == NULL) { ll->tail = node; } node->next = ll->head; ll->head = node; ll->length++; } void ll_push_tail(struct linkedlist *ll, char *data) { struct ll_node *node = malloc(sizeof(struct ll_node)); ll_no
- pattern minor 112d agoObject pool pattern for asynchronous socket operationsI have written my own object pool class called `ObjectPool` which uses `SpinLock` and `Stack`: ``` public class ObjectPool where T : class { private int _size; private Func _factory; private SpinLock _spinLock; // storage for the pool objects. // the first item is expected to be most often case. private T _firstItem; private Stack _cache; //Use Queue for first-in-first-out (FIFO) public ObjectPool(Func factory) : this(factory, Environment.ProcessorCount * 2) { } public ObjectPool(Func factory, int size) { _factory = factory; _size = size; _cache = new Stack(); _spinLock = new SpinLock(false); } /// /// Produces an instance. /// public T Rent() { bool lockTaken = false; _spinLock.Enter(ref lockTaken); try { T instance = _firstItem; if (instance == null || instance != Interlocked.CompareExchange(ref _firstItem, null, instance)) { instance = RentFromCache(); } return instance; } finally { if (lockTaken) { _spinLock.Exit(false); } } } private T RentFromCache() { var cache = _cache; if (cache.Count > 0) { T instance = _cache.Pop(); if (instance != null) { return instance; } } return CreateInstance(); } private T CreateInstance() { var instance = _factory(); return instance; } /// /// Returns objects to the pool. /// public void Return(T obj) { bool lockTaken = false; _spinLock.Enter(ref lockTaken); try { if (_firstItem == null) { // worst case scenario: two objects may be stored into same slot. _firstItem = obj;
- pattern minor 112d agoQueue with multiple consumers and one producerI've written a queue supporting one producer and multiple consumer threads. The idea is that the queue instances a definable number of long running consumer threads. Internally I'm using a `BlockingCollection` to solve the producer consumer problem. I've done some little testing via a console application, and it seems to work. Can somebody review the code and let me know if there is any flaw? The code can be found under Github. Example usage: ``` static void Main(string[] args) { var q = new QueueWithMultipleConsumerThreads( numberOfWorkerThreads: 10, actionToBeCalled: i => { Console.WriteLine($"Consumed {i} from thread {Thread.CurrentThread.Name}, id: {Thread.CurrentThread.ManagedThreadId}"); }); // Add some entries to the q for (int i = 0; i < 10000; i++) { q.Enque(i); } Thread.Sleep(5000); // Give the q time to work q.Shutdown(); } ``` QueueWithMultipleConsumerThreads: ``` public class QueueWithMultipleConsumerThreads { private readonly ConcurrentBag threads = new ConcurrentBag(); private readonly ConcurrentBag> workers = new ConcurrentBag>(); private readonly BlockingCollection queue = new BlockingCollection(); public QueueWithMultipleConsumerThreads(uint numberOfWorkerThreads, Action actionToBeCalled ) { if (numberOfWorkerThreads == 0) { throw new ArgumentException($"{nameof(numberOfWorkerThreads)} must be > 0"); } if (actionToBeCalled == null) { throw new ArgumentNullException(nameof(actionToBeCalled));} for (var i = 0; i (this.queue, threadName, actionToBeCalled, logger); var t = new Thread(w.DoWork) { IsBackground = true, Name = threadName}; this.workers.Add(w); this.threads.Add(t); t.Start(); } } public void Enque(T item) { this.queue.Add(item); } public int Count() { return this.queue.Count; } publ
- pattern minor 112d agoJavaScript QueueI'm new to JS and have I made this snippet for practicing. Because I have no idea for JS conventions, I want some advice about that. ``` function Queue() { this.list = new Array(); this.pop = function() { return this.list.pop() }; this.push = function(el) { this.list.unshift(el); }; this.size = function() { return this.list.length; }; this.isEmpty = function() { return this.size() == 0; } this.print = function() { var res = '('; for (var i = 0; i '; document.write(res); } this.front = function() { return this.list[0]; } this.back = function() { return this.list[this.list.length-1]; } } /* test code */ var myQueue = new Queue(); myQueue.push(1); myQueue.print(); myQueue.push(2); myQueue.print(); myQueue.push(3); myQueue.print(); myQueue.push(4); myQueue.print(); myQueue.push(5); myQueue.print(); myQueue.pop(); myQueue.print(); myQueue.pop(); myQueue.print(); myQueue.pop(); myQueue.print(); myQueue.pop(); myQueue.print(); myQueue.pop(); ```
- pattern minor 112d agoTCP retarder for network delay simulationI would like to simulate delay over network, for that I have implemented a simple retarder (=introduce random delay while maintaining order of messages) using Boost to handle sending itself. It appears to work as intended. However, since parallel programming is not trivial especially when coupled with networking, I would like to hear feedback more experienced C++ programmer. Mostly, I am concerned about the parallelization(deadlocks, resource leaks) and possible side effects on the communication I might have missed. ``` class SendRetarder { typedef std::pair args_t;//to whom and what std::queue message_queue;//messages to be sent std::mutex m; std::condition_variable cv; const size_t max_wait = 10000; void send_loop() { while (true) { boost::system::error_code ec; args_t args; size_t wait; { std::unique_lock lk(m); cv.wait(lk, [&] { return !message_queue.empty(); }); wait = (rand() % max_wait) / message_queue.size();//to prevent unchecked growing args = message_queue.front(); message_queue.pop(); } std::this_thread::sleep_for(std::chrono::milliseconds(wait)); boost::asio::write(args.first->socket_, boost::asio::buffer(&args.second, sizeof(message_t)), ec); if (ec) std::cerr lk(m); message_queue.push(args_t(client, msg)); } cv.notify_one(); } }; ``` where `message_t` is the contents of the message consisting of integer types and `session_ptr` is a smart pointer wrapper around socket shared with client itself: ``` struct message_t { msg_id_t message_id; tag_t message_tag; sender_t sender_id; union { uint32_t value; bool success; } data; } typedef std::shared_ptr session_ptr; class Session : public std::enable_shared_from_this { tcp::socket socket_; sender_t name_; //... } ```