Saturday, January 13, 2018

Digest for comp.lang.c++@googlegroups.com - 20 updates in 11 topics

"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: