- simple atomic lifo... - 1 Update
- About the following algorithms - 3 Updates
- Here is my new model.. - 1 Update
- The Truth - 1 Update
- Some classic (GoF) design patterns are no longer needed in C++ - 4 Updates
- Semantics of comma operator - 4 Updates
- Go to church this Sunday - 1 Update
- Semantics of comma operator - 2 Updates
- About morality - 1 Update
- Here is again Sir Flibble - 1 Update
- About Sir Flibble - 1 Update
"Chris M. Thomasson" <invalid_chris_thomasson@invalid.invalid>: Jan 13 03:10PM -0800 A simple LIFO algorithm... Any questions? ;^) __________________________ #define mb_relaxed std::memory_order_relaxed #define mb_consume std::memory_order_consume #define mb_acquire std::memory_order_acquire #define mb_release std::memory_order_release #define mb_acq_rel std::memory_order_acq_rel #define mb_seq_cst std::memory_order_seq_cst #define mb_fence(mb) std::atomic_thread_fence(mb) // simple single producer/multi-consumer queue struct node { node* m_next; node() : m_next(nullptr) {} // tidy... }; struct spmc_queue { std::atomic<node*> m_head; spmc_queue() : m_head(nullptr) {} // push a single node void push(node* const n) { node* head = m_head.load(mb_relaxed); for (;;) { n->m_next = head; mb_fence(mb_release); if (m_head.compare_exchange_weak(head, n, mb_relaxed)) { break; } } } // try to flush all of our nodes node* flush() { node* n = m_head.exchange(nullptr, mb_relaxed); if (n) { mb_fence(mb_acquire); } return n; } }; __________________________ Here is an example program that uses it: __________________________ #include <cstdio> #include <mutex> #include <memory> #include <thread> #include <atomic> #include <algorithm> #include <cassert> #define mb_relaxed std::memory_order_relaxed #define mb_consume std::memory_order_consume #define mb_acquire std::memory_order_acquire #define mb_release std::memory_order_release #define mb_acq_rel std::memory_order_acq_rel #define mb_seq_cst std::memory_order_seq_cst #define mb_fence(mb) std::atomic_thread_fence(mb) // Just a check... static std::atomic<unsigned long> g_alloc_count(0); // simple single producer/multi-consumer queue struct node { node* m_next; node() : m_next(nullptr) {} // tidy... }; struct spmc_queue { std::atomic<node*> m_head; spmc_queue() : m_head(nullptr) {} // push a single node void push(node* const n) { node* head = m_head.load(mb_relaxed); for (;;) { n->m_next = head; mb_fence(mb_release); if (m_head.compare_exchange_weak(head, n, mb_relaxed)) { break; } } } // try to flush all of our nodes node* flush() { node* n = m_head.exchange(nullptr, mb_relaxed); if (n) { mb_fence(mb_acquire); } return n; } }; // Spin-Wait, Blocking Adapt Function node* spmc_queue_spin_lock_flush( spmc_queue& queue ) { node* n = nullptr; for (;;) { n = queue.flush(); if (n) break; std::this_thread::yield(); } return n; } #define CONSUMERS 7 #define N 1000000 struct user_data : public node { int m_foo; user_data(int foo) : m_foo(foo) {} }; void producer_thread( unsigned int id, std::mutex& std_out_mutex, spmc_queue& queue ){ { std::unique_lock<std::mutex> lock(std_out_mutex); std::printf("producer(%u)::queue(%p) - Entry\n", id, (void*)&queue); } for (unsigned int i = 0; i < N; ++i) { user_data* ud = new user_data(i + 1); // allocate memory g_alloc_count.fetch_add(1, mb_relaxed); queue.push(ud); if (! ((i + 1) % 1003)) { std::unique_lock<std::mutex> lock(std_out_mutex); std::printf("producer(%u)::queue(%p) - produced(%u)\n", id, (void*)&queue, i + 1); } } for (unsigned int i = 0; i < CONSUMERS; ++i) { user_data* ud = new user_data(0); // allocate memory g_alloc_count.fetch_add(1, mb_relaxed); queue.push(ud); } { std::unique_lock<std::mutex> lock(std_out_mutex); std::printf("producer(%u)::queue(%p) - Exit\n", id, (void*)&queue); } } void consumer_thread( unsigned int id, std::mutex& std_out_mutex, spmc_queue& queue ){ { std::unique_lock<std::mutex> lock(std_out_mutex); std::printf("consumer(%u)::queue(%p) - Entry\n", id, (void*)&queue); } { for (unsigned long i = 0 ;; ++i) { // Wait for something... user_data* ud = (user_data*)spmc_queue_spin_lock_flush(queue); assert(ud); // make sure we have something! int counter = 0; while (ud) { node* ud_next = ud->m_next; unsigned int foo = ud->m_foo; delete ud; // reclaim memory g_alloc_count.fetch_sub(1, mb_relaxed); if (foo == 0) { // We have recieved a "stop" signal counter++; } if (!((i + 1) % 1003)) { std::unique_lock<std::mutex> lock(std_out_mutex); std::printf("consumer(%u)::queue(%p) - consumed(foo:%u)\n", id, (void*)&queue, foo); } ud = (user_data*)ud_next; } std::this_thread::yield(); // just for spice... while (counter > 1) { // Replay all of the excess stop signals user_data* ud = new user_data(0); // allocate memory g_alloc_count.fetch_add(1, mb_relaxed); queue.push(ud); --counter; { std::unique_lock<std::mutex> lock(std_out_mutex); std::printf("consumer(%u)::queue(%p) - replay(%u)*****************\n", id, (void*)&queue, counter); } } if (counter == 1) { // We are fin! break; } } } { std::unique_lock<std::mutex> lock(std_out_mutex); std::printf("consumer(%u)::queue(%p) - Exit\n", id, (void*)&queue); } } int main(void) { { spmc_queue queue; std::thread consumers[CONSUMERS]; std::mutex std_out_mutex; for (unsigned int i = 0; i < CONSUMERS; ++i) { consumers[i] = std::thread( consumer_thread, i + 1, std::ref(std_out_mutex), std::ref(queue) ); } std::thread producer( producer_thread, 0, std::ref(std_out_mutex), std::ref(queue) ); producer.join(); for (unsigned int i = 0; i < CONSUMERS; ++i) { consumers[i].join(); } } std::printf("g_alloc_count:(%lu)\n", g_alloc_count.load(mb_relaxed)); assert(g_alloc_count.load(mb_relaxed) == 0); std::printf("\nComplete, hit <ENTER> to exit...\n"); std::fflush(stdout); std::getchar(); return 0; } __________________________ Can anybody else run this? |
"Chris M. Thomasson" <invalid_chris_thomasson@invalid.invalid>: Jan 13 01:40PM -0800 On 1/12/2018 5:41 PM, Mr Flibble wrote: > BTW, you are not the first to create a LIFO stack-based allocator (so > you can't claim to have "invented it") and you won't be the last: I am > thinking of making one myself. Fwiw, check this out: https://groups.google.com/d/topic/comp.lang.c++/yt27gw0cbyo/discussion No padding and cache alignment here in the crude code, but the algorithm is shown for spmc_queue::push and spmc_queue::flush -> (trimmed from the original program) contained within the contents of the link above: C++11 compatible... __________________________ #define mb_relaxed std::memory_order_relaxed #define mb_consume std::memory_order_consume #define mb_acquire std::memory_order_acquire #define mb_release std::memory_order_release #define mb_acq_rel std::memory_order_acq_rel #define mb_seq_cst std::memory_order_seq_cst #define mb_fence(mb) std::atomic_thread_fence(mb) // simple single producer/multi-consumer queue struct node { node* m_next; node() : m_next(nullptr) {} // tidy... }; struct spmc_queue { std::atomic<node*> m_head; spmc_queue() : m_head(nullptr) {} // push a single node void push(node* const n) { node* head = m_head.load(mb_relaxed); for (;;) { n->m_next = head; mb_fence(mb_release); // failure updates head... if (m_head.compare_exchange_weak(head, n, mb_relaxed)) { break; } } } // try to flush all of our nodes node* flush(node* const nhead = nullptr) { node* n = m_head.exchange(nhead, mb_relaxed); if (n) { mb_fence(mb_acquire); } return n; } }; __________________________ Well, this is can be a queue and a stack at the same time... The non-nullptr result from spmc_queue::flush can be used as-is for LIFO. However, if you reverse the list, a FIFO nature pops out of the queue as a whole. Any thoughts? |
"Chris M. Thomasson" <invalid_chris_thomasson@invalid.invalid>: Jan 13 01:47PM -0800 On 1/13/2018 1:40 PM, Chris M. Thomasson wrote: >> On 13/01/2018 06:04, Intelli2 wrote: >>> On 1/12/2018 7:47 PM, Mr Flibble wrote: >>>> On 13/01/2018 05:40, Intelli2 wrote: [...] > node* m_next; > node() : m_next(nullptr) {} // tidy... > }; Each node should ideally be the size of a cache line. sizeof(struct node) == CACHE_LINE. > struct spmc_queue > { > std::atomic<node*> m_head; This head should be on its own cache line and a point to spmc_queue should be aligned on a cache line boundary in memory. A pointer to spmc_queue::m_head should be aligned on a cache line boundary. This should be a damn POD! The constructor in struct node should be removed in favor of an explicit initialization function. [...] |
"Chris M. Thomasson" <invalid_chris_thomasson@invalid.invalid>: Jan 13 02:44PM -0800 On 1/13/2018 1:40 PM, Chris M. Thomasson wrote: > { > std::atomic<node*> m_head; > spmc_queue() : m_head(nullptr) {} [...] > node* flush(node* const nhead = nullptr) Still forgot to mention that if nhead is not equal to nullptr in flush, the calling thread needs to ensure release membar semantics before calling this function! If nhead is not nullptr the calling code in inserting a new LIFO object in place of the existing LIFO. Also, if you call flush with a LIFO, make sure the damn last node has a null next pointer! Humm... I this adding the nhead in flush makes it too complicated. > node* flush(node* const nhead = nullptr) > { // Release fence wrt non null nhead if (nhead != nullptr) { mb_fence(mb_release); } |
Intelli2 <intelli2@mama.com>: Jan 13 05:31PM -0500 Hello, Read this: Here is my new model.. I have Thought and thought and i have come with a new model, how can we model correctly humans? we have to look at the variables like the variable that someone is more or less violent and the variable that someone is more or less tolerant, and the variable that someone is more or less compassion that will render him more social or not, and there is also the variable that someone is more or less bravery, so if someone is less brave and/or less violent this is highly correlated and it causes the fact that he fears risk that hurts, so he will takes care more correctly of security, i give you an example: You will notice here on the internet forum, that many are less scientific or less technical even though that being more scientific and/or more technical causes human to be more security, because being more science and more technical is being more security that knows how to govern oneself and that knows how to govern the group, this is why i think that someone that is less bravery or less violent is someone that fears the risk that can hurt, so he will start to be more science and be more technical and be more rational so that to be more security for oneself and for the others. This is my new model. Thank you, Amine Moulay Ramdane. |
"Rick C. Hodgin" <rick.c.hodgin@gmail.com>: Jan 13 09:44PM The truth is I have no evidence that my god exists but I refuse to accept so called rational scientific evidence that my god doesn't exist because it contradicts my irrational faith. I also refuse to accept that the Earth isn't flat for the same reasons: my irrational faith trumps all rational science which is a deceitful fiction designed by Satan to make us leave the true path of faith in Jesus Christ and his bastard son Santa Claus that he begat with Mary Magdalane. Also, the moon landings didn't happen because the moon is made of cheese so its surface wouldn't have been able to support the weight of the Apollo Lunar Module; it was faked in a TV studio directed by Stanley Kubrick. I go to a building called a church on Sundays because it is a place where I can have my biases reaffirmed which is something I like; this is standard practice for most Christians. -- Thank you, Rick C. Hodgin |
bitrex <bitrex@de.lete.earthlink.net>: Jan 13 10:47AM -0500 On 01/13/2018 02:46 AM, Christian Gollwitzer wrote: > computational power as C++, but you wouldn't actually want to write code > like that. > Christian Lots of disciplines have "patterns" and IMO the reason they exist is mainly to give some "axiomatic" structure to design problems where the degrees of freedom greatly exceeds the number of constraints, that is to say the problem is under-determined. The fact that the problem is under-determined doesn't change the fact that some solution or other needs to be produced. There might be some optimal-for-an-application solution that involves a structure completely unrelated to any known "pattern", maybe blows all of them away by a mile, in fact. How will you ever find it? |
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Jan 13 05:34PM On 13/01/2018 09:35, Chris Vine wrote: >> } > Your examples are completely contrived. Yes, you can allocate > heap-like storage on the stack of the main function, but you are My examples are not contrived at all in fact this is key to the elegance of the API of neoGFX (my C++ GUI library): when adding a child widget to a layout or parent widget that child widget can be allocated either on the free store or on the stack and the std::shared_ptr aliasing constructor is utilized in achieving this. > proportions, nor quite as exciting as your announcements about fixed > size integer types. On std::function, you have come to the party 7 > years late, but you got there in the end. I have been using std::function for at least 10 years so how does that tally with me "coming to the party 7 years late"? /Flibble -- "Suppose it's all true, and you walk up to the pearly gates, and are confronted by God," Bryne asked on his show The Meaning of Life. "What will Stephen Fry say to him, her, or it?" "I'd say, bone cancer in children? What's that about?" Fry replied. "How dare you? How dare you create a world to which there is such misery that is not our fault. It's not right, it's utterly, utterly evil." "Why should I respect a capricious, mean-minded, stupid God who creates a world that is so full of injustice and pain. That's what I would say." |
Melzzzzz <Melzzzzz@zzzzz.com>: Jan 13 05:59PM > A main feature of the (original) command pattern is support for undo > functionality. > I fail to see how `std::function` does that. Well, std::function holds function object, no? It can call do/undo whatever, you can place std::functions in a list... -- press any key to continue or any other to quit... |
cdalten@gmail.com: Jan 13 01:32PM -0800 Someone about a decade ago showed that every design pattern was just special case of the map? function based off the Lambda Calculus. |
James Kuyper <jameskuyper@verizon.net>: Jan 13 01:42PM -0500 On 01/12/2018 11:49 AM, Stefan Ram wrote: >> For some reason, this is all I see when I view your message: > It seems that you are replying to some message, > but your post does not have a reference header. I would imagine that's because, as received by my newsreader, the message didn't have enough information to construct a reference header. When I did "View Source" on the message, I only got an empty screen - which makes me wonder how Thunderbird constructed the line it displays on the screen for that message, which contains the Subject, From, and Date. Obviously, something is badly messed up. The message I was responding to was posted by you, with this subject, quite recently, and apparently (judging by it's position in the display) as a response to a message of mine. If you know of any such message, could you either re-post it, or at least e-mail me a copy? |
James Kuyper <jameskuyper@verizon.net>: Jan 13 01:49PM -0500 On 01/12/2018 11:23 AM, Stefan Ram wrote: >> of the file, rather than to the end of what was written to the file. > Sometimes, a function to count the number of possible calls > to getc might help. I have written - but not tested - such ... Keep in mind that, on the systems I was referring to, such an approach might result in reading the padding null characters at the end of the file, and including them in the file size. |
Bonita Montero <Bonita.Montero@gmail.com>: Jan 13 08:06PM +0100 > while ((c = fgetc (in)), c != EOF) I use it often similary. But in this case you can omit the parenthesis around "(c = fgetc (in))" becuase the comma-operator has the lowest precedence. I also use the comma-operator for small blocks when there isn'T no any control-structures and I have a low line-count in the "block". |
Keith Thompson <kst-u@mib.org>: Jan 13 01:29PM -0800 Geoff <geoff@invalid.invalid> writes: [...] > It is in a C context. I managed to post the question in the wrong > group somehow. It is a text file opened with "rt" flags in the fopen > call. "rt" as the second argument to fopen() is non-standard (neither ISO C nor POSIX describes it). Apparently in some implementations it's treated as equivalent to "r". -- Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst> Working, but not speaking, for JetHead Development, Inc. "We must do something. This is something. Therefore, we must do this." -- Antony Jay and Jonathan Lynn, "Yes Minister" |
"Rick C. Hodgin" <rick.c.hodgin@gmail.com>: Jan 13 01:25PM -0800 You see me write about sin and condemnation, and eternal Hellfire (damnation), and also how to avoid that end by coming to Jesus, and asking Him to forgive you and save you from Hell. But how do you know I'm telling you the truth? You read the New Testament for yourself, and you go to a Christian church and ask people questions face-to-face. Do not take anyone's word for information for OR AGAINST the Bible, or about Jesus. Go to the source yourself, and see from the source yourself. If you do this, you'll learn the truth. The truth will make you free. I love you. Go to church and ask people questions. Demand answers and make them show you in the Bible where they have found their answers. Do not compromise. Truly demand the truth. -- Rick C. Hodgin |
ram@zedat.fu-berlin.de (Stefan Ram): Jan 13 07:47PM >quite recently, and apparently (judging by it's position in the display) >as a response to a message of mine. If you know of any such message, >could you either re-post it, or at least e-mail me a copy? Thanks for your interest in my messages! Of course, I was looking for the reference header so as to get to know /which/ message it was that you were asking for. But from the context it seems that this should have been the message <getc-count-20180112172146@ram.dialup.fu-berlin.de> that you then replied to in your message <p3dkbh$ek8$1@dont-email.me> , so I hope that by now you have already read all messages I posted recently into this group. Maybe some agent has inserted a spurious and incomplete copy of my message. The last message I posted before the message <getc-count-20180112172146@ram.dialup.fu-berlin.de> was <stream_to_char-20180109191433@ram.dialup.fu-berlin.de> and the next message I posted after the message <getc-count-20180112172146@ram.dialup.fu-berlin.de> was <askSample-20180112174414@ram.dialup.fu-berlin.de> . |
ram@zedat.fu-berlin.de (Stefan Ram): Jan 13 07:52PM >Keep in mind that, on the systems I was referring to, such an approach >might result in reading the padding null characters at the end of the >file, and including them in the file size. I already added an option »stop_on_zero« to interpret NUL as EOF (in the message you reply to above), but possibly I should redefine this to only interpret NUL as EOF /if/ no other non-NUL char is following the NUL. |
mcheung63@gmail.com: Jan 13 09:30AM -0800 Intelli2於 2018年1月13日星期六 UTC+8上午10時07分26秒寫道: > and is inferior. > Thank you, > Amine Moulay Ramdane. Go die with Rick C. Hodin, his fucking mum is wait for you in hell, when you reach there, her pussy is yours, go fuck it. |
mcheung63@gmail.com: Jan 13 09:29AM -0800 Mr Flibble於 2018年1月13日星期六 UTC+8上午9時43分39秒寫道: > that is not our fault. It's not right, it's utterly, utterly evil." > "Why should I respect a capricious, mean-minded, stupid God who creates > a world that is so full of injustice and pain. That's what I would say." /he is big fans of Rick C. Hodin, he is completely idiot |
mcheung63@gmail.com: Jan 13 09:28AM -0800 Intelli2於 2018年1月13日星期六 UTC+8上午9時23分07秒寫道: > Trump also has to control more himself because it's genetical in them. > Thank you, > Amine Moulay Ramdane. Are you Rick C. Hoding asshole? |
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page. To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com. |
No comments:
Post a Comment