473,785 Members | 2,309 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Is this standard c++...

I am thinking about using this technique for all the "local" memory pools in
a paticular multi-threaded allocator algorithm I invented. Some more info on
that can be found here:

http://groups.google.com/group/comp....c40d42a04ee855

Anyway, here is the code snippet:

#include <cstdio>
#include <cstddef>
#include <new>
template<size_t T_sz>
class lmem {
unsigned char m_buf[T_sz];
public:
void* loadptr() {
return m_buf;
}
};
class foo {
public:
foo() { printf("(%p)foo ::~foo()", (void*)this); }
~foo() { printf("(%p)foo ::~foo()", (void*)this); }
};
int main(void) {
foo *f;
lmem<sizeof(*f) foomem;
f = new (foomem.loadptr ()) foo;
f->~foo();
return 0;
}

Feb 27 '07
22 2301
"kwikius" <an**@servocomm .freeserve.co.u kwrote in message
news:11******** *************@n 33g2000cwc.goog legroups.com...
On 2 Mar, 11:48, "Chris Thomasson" <cris...@comcas t.netwrote:

<...>
>Any thoughts?

First I don't know enough about threads to make any constructive
commnts.
<an "on the soap box" like statement>
I know that you know more than you think you do.... The steps that are
necessary in order to realize a constructive use of concurrency in general
eventually end up being a strict lesson in common sense... Well, of course
you, and "virtually" all of us, are already "blessed" with some form of
ingrained comment sense. So, do you have what it takes to make interesting
and good uses of multithreading techniques, IMHO, of course you do!

Never sell yourself short wrt any aspect of what you can and cannot
learn!... :O
</an "on the soap box" like statement>

;^)

OTOH give me access to the system timer and program counter
and ability to disable interrupts and allow me to write interrrupt
service routines, in fact control of the system event mechanisms and I
would be happy.
Yup. I remember the good old days when I was implementing the early stages
of operating system loading processes. Kind of gives you a GOD complex
though. I mean, you get to fill in all of the interrupt vectors with your
stuff, and you have access to those wonderful hardware control words. Good
times!

OTOH I guess I should head over to the threads
newsgroup and try to understand them better.
We would be happy to help you. That group needs some more traffic anyway!
Seems like its sort of "dead" at times... So, if you end up handing out some
more on comp.programmin g.threads, go ahead an tell some of your friends
about it! BTW, David Butenhof hangs around there sometimes... Indeed you can
have some of the worlds best threading gurus give a little introspection on
any question you may have. Okay, enough with the "salesman" crap! :O Sorry.

Anyway here are some
thoughts (in contradiction to the above) thouh I havent studied your
code in any depth:
Okay.

Firstly I don't understand from that the way you want to use the
device, but I would guess it would be restricted to specialised use,
however a few (confused) thoughts spring to mind.
First of all, let me provide a "quick introduction" on all of my subsequent
comments:

"I want the device to be able to provide the end user with the exact same
functionality as the following ANSI C functions do:

extern "C" {
extern void* malloc(size_t);
extern void free(void*);
}

with the following exception: malloc and free are going to be 100%
thread-safe. The low-level synchronization scheme is going to exist in
per-thread data-structures. Any allocations that cannot be safely and
efficiently addressed by the per-thread scheme (e.g., the "local heap") will
be subjected to an allocation from the "global heap". In other words, if
allocations are sufficiently small in size (e.g., sizeof(void*) to 256 bytes
are fine), then all aspects of the device will be completely utilized. The
devices "global heaps" will be invoked for everything else.

The device is able to accommodate highly efficient threading designs. For
instance, if your threads keep their allocations local, then the device will
not use any multiprocessor synchronization techniques at all. It will be
equivalent to a single-threaded allocation. The device WILL make use of an
interlocked RMW instruction and a memory barrier (e.g., CAS and SPARC's
membar #StoreStore) ONLY IF your threads can "pass allocations around
amongst themselves", AND, "the thread that allocated an object 'A' winds up
not being the thread that eventually frees object 'A'"
"

The first is that in
my environment the stack is actually quite a scarce resource, default
around 1 Mb (In VC7.1), after which you get a (non C++) stack overflow
in VC7.1. I presume you can modify this though.
Yes. Most threading abstractions allow one to setup a threads individual
stack size. Actually, and in IMHO of course, a "lot of programs" don't
really end up making "complete" use of that 1MB stack... Also, lets try to
keep in mind that virtually any so-called "competent" system that makes use
of some form of recursion has to have a method for "ensuring that there is
enough space on the stack to accommodate the complete depth of the recursive
operation".

The heap on the other hand can be looked on as a(almost) infinite
resource, even if you run out of physical memory the system will start
swapping memory to from disk. Very system specific though I guess..
Indeed it is system specific. However, you raise a critical point. I address
this scenario by funneling all allocations that the per-thread part of my
allocator implementation cannot address through an abstraction of the OS
heap. The abstraction can be as simple as a call to the OS provided standard
C library malloc function. My stuff essentially sits on top of the threads
stacks and uses malloc to enable it to not fall off when it runs out of
memory during "high-stress" situations that a multi-threaded user
application can sometimes, and usually will end up generating.

In that sense I would guess that use of the stack is by nature not as
scaleable as using the heap.
Which is exactly why I am forced to use the heap as a slow-path in my
current implementation of the allocator algorithm.

So from that point of view it is interesting to try to come up with
scenarios where you would use the device.
Thanks! IMHO, the allocator works perfectly when you try to make any
deallocations of a memory block 'X' occur in the same thread that originally
allocated block 'X' in the first place. IMHO, I can sort of "get away" with
using the phrase "works perfectly" simply because the allocator endures no
more overhead than a single-threaded allocator would when an application
tryst real hard to keep things "thread local". My invention will use an
interlocked RMW instruction and a #StoreStore memory barrier to "penalize
any thread that tries to deallocate a memory block that it did not allocate
itself!". Everything is lock-free, however, as we all should know,
interlocked RMW and/or memory barrier instructions are fairly expensive for
basically any modern processor to execute. They tend to have the unfortunate
side-effect of blowing any cache the CPU has accumulated and devastating
part of any pipelined operations that were pending. This type of behavior
can gravely wound a number of aspects that are involved with scalability and
throughput in general.

>>From the viewpoint of allocationg on the stack, essentially you have
to know how much you are going to allocate beforehand, but if the
stack is a scarce resource,its not viable to treat it in the same
carefree way as the heap proper and just allocate huge. Of course it
may be possible to use some assembler to write your own functions
grabbing runtime amounts of stack, which would maybe make the device
more versatile.
Perhaps. I am leaning toward keeping things local, and using a thin API
layer around the OS heap as a sort of "last resort".

For use as an allocator, the alternative is of course to use malloc
for your one time start up allocation for your own allocator, and then
after the start up cost whether you allocated on the heap or stack I
would guess the cost of getting memory from the allocator is going to
be the same regardless where it is.
Great point. Perhaps I am being a bit unpractical wrt my line of thought
that most programs don't make use of the fairly large default stack size the
OS regularly hands end up handing out to a processes threads. Anyway, I kind
of like the idea of not having to make use of malloc when you have perfectly
good, and most likely unused, stack space sitting around on your
applications threads. The synchronization scheme I created allows for a
thread 'A' to allocate a memory block 'X' and subsequently pass it around to
threads 'B' through 'Z'. So, thread 'B' can use block 'X' even though the
memory the makes up block 'X' resides on thread 'A' stack. Humm... Your
solution to the problem (e.g., use malloc to provide the allocators
per-thread data-structures) is well grounded in common sense. Like I said,
perhaps I am being a bit unpractical here... Well, screw it! I think its
neat that an allocator can use a plurality use threads stacks for most of
its allocations.

;^)

[...]
This does somehow
bring to mind use in embedded systems where there is no heap as such
so the scheme could be used as a heap for systems without a heap as it
were.
Ahh yes. That sure seems like it could possible come in handy in that type
of situation! Indeed. Thanks for your comments!

:^)

You would then presumably need to keep passing a reference to
the allocator in to child functions or put it in a global variable.
My allocators system data-structures rely on a given platform to provide
each of its threads with a stack space large enough to hold at least 4 to 8
kilobytes, a function that is analogous to pthread_get/setspecific(... )
and/or pthread_self(), an interlocked RMW (e.g., CAS or even LL/SC), and of
course (e.g., assuming you looked at the pseudo-code implementation) , a
#StoreStore memory barrier instruction. Luckily for me, CAS and LL/SC are
fairly common, and if there not there, well, they can certainly be emulated
with a hashed locking pattern. If the platform has no interlocked RMW
instructions, or mutexs, then the multi-threaded aspect of my allocator
cannot be realized.

Overall then its difficult to know where the advantages outweigh the
difficulties.
Hopefully, I cleared some things up. What do ya think Andy?

:^)
Mar 3 '07 #21
Okay... Here is a snippet of some compliable example code:
<code>

#include <cstdio>
#include <cstddef>
#include <cassert>
#include <new>
template<size_t T_basesz, size_t T_metasz, size_t T_basealign>
class lmem {
unsigned char m_basebuf[T_basesz + T_metasz + T_basealign - 1];
unsigned char *m_alignbuf;

private:
static unsigned char* alignptr(unsign ed char *buf, size_t alignsz) {
ptrdiff_t base = buf - static_cast<uns igned char*>(0);
ptrdiff_t offset = base % alignsz;
ptrdiff_t result = (! offset) ? base : base + alignsz - offset;
assert(! (result % alignsz));
return static_cast<uns igned char*>(0) + result;
}

public:
lmem() : m_alignbuf(alig nptr(m_basebuf, T_basealign)) {
printf("(%p)lme m::lmem()\n - buffer size: %u\n - m_basebuf(%p)\n -
m_alignbuf(%p)\ n\n",
(void*)this,
T_basesz + T_metasz + T_basealign - 1,
(void*)m_basebu f,
(void*)m_alignb uf);
}
template<typena me T>
void* loadptr() const {
assert(T_basesz >= (sizeof(T) * 2) - 1);
printf("(%p)lme m::loadptr() - buffer size: %u\n",
(void*)this,
(sizeof(T) * 2) - 1);
return alignptr(m_alig nbuf, sizeof(T));
}
void* loadmetaptr() const {
return m_alignbuf + T_basesz;
}
};
namespace detail {
namespace os {
namespace cfg {
enum config_e {
PAGE_SZ = 8192
};
}}

namespace arch {
namespace cfg {
enum config_e {
L2_CACHELINE_SZ = 128
};
}}

namespace lheap {
namespace cfg {
enum config_e {
BUF_SZ = os::cfg::PAGE_S Z * 2,
BUF_ALIGN_SZ = arch::cfg::L2_C ACHELINE_SZ,
BUF_METADATA_SZ = sizeof(void*)
};
}}
}
template<typena me T>
class autoptr_calldto r {
T *m_ptr;
public:
autoptr_calldto r(T *ptr) : m_ptr(ptr) {}
~autoptr_calldt or() {
if (m_ptr) { m_ptr->~T(); }
}
T* loadptr() const {
return m_ptr;
}
};
namespace lheap {
using namespace detail::lheap;
}
class foo1 {
// mess with the stack
int m_1;
char m_2[73];
short m_3;
char m_4[18];
public:
foo1() { printf("(%p)foo 1::foo1()\n", (void*)this); }
~foo1() { printf("(%p)foo 1::~foo1()\n\n" , (void*)this); }
};
class foo2 {
// mess with the stack
int m_1;
char m_2[111];
short m_3;
char m_4[222];
public:
foo2() { printf("(%p)foo 2::foo2()\n", (void*)this); }
~foo2() { printf("(%p)foo 2::~foo2()\n\n" , (void*)this); }
};
int main() {
// mess with the stack
int m_1;
char m_2[73];
short m_3;
char m_4[18];

{
// setup this threads allocator
lmem<lheap::cfg ::BUF_SZ,
lheap::cfg::BUF _METADATA_SZ,
lheap::cfg::BUF _ALIGN_SZfoomem ;

{
// mess with the stack
int m_1;
char m_2[142];
short m_3;
char m_4[188];

autoptr_calldto r<foo1f(new (foomem.loadptr <foo1>()) foo1);
}

{
// mess with the stack
int m_1;
char m_2[1];
short m_3;
char m_4[3];

autoptr_calldto r<foo2f(new (foomem.loadptr <foo2>()) foo2);
}
}

printf("\n_____ ____\npress any key to exit...\n");
getchar();
return 0;
}

</code>

Can anybody run this without tripping an assertion? It seems to be running
fine on my systems...

;^)
P.S.

This should compile fine with the following options:

-Wall -pedantic -ansi

If you have any problems, let me know.
Mar 3 '07 #22
On 3 Mar, 09:07, "Chris Thomasson" <cris...@comcas t.netwrote:
Hopefully, I cleared some things up. What do ya think Andy?
I think I'd better pull back out of discussions re threads and leave
it to the experts :-)

regards
Andy Little
Mar 5 '07 #23

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

25
3795
by: Magnus Lie Hetland | last post by:
Is there any interest in a (hypothetical) standard graph API (with 'graph' meaning a network, consisting of nodes and edges)? Yes, we have the standard ways of implementing graphs through (e.g.) dicts mapping nodes to neighbor-sets, but if one wants a graph that's implemented in some other way, this may not be the most convenient (or abstract) interface to emulate. It might be nice to have the kind of polymorphic freedom that one has with,...
6
8331
by: John Bentley | last post by:
John Bentley writes at this level: If we think about our savings accounts then division never comes in (as far as I can see). We deposit and withdraw exact amounts most of the time. Occasionaly we get an interest payment. Unless the bank is cruel to its developers the interest figure will be able to be exactly represented by a computer, something like 4.1% as opposed to 4 1/3 % 125.78 * ' Initial Balance 04.1% -------
29
2410
by: David Eng | last post by:
In replying to P.J. Plauger ( http://groups.google.com/groups?dq=&hl=en&lr=&ie=UTF-8&threadm=1089204435.746211%40master.nyc.kbcfp.com&prev=/groups%3Fhl%3Den%26lr%3D%26ie%3DUTF-8%26group%3Dcomp.lang.c%252B%252B.moderated ) who responded my post in comp.long.c++ moderated neww group regarding "C++ standard and C++/CLI" topic, I worte the following post which was sensor by comp.lang.c++.moderated: ...
43
5026
by: Steven T. Hatton | last post by:
Now that I have a better grasp of the scope and capabilities of the C++ Standard Library, I understand that products such as Qt actually provide much of the same functionality through their own libraries. I'm not sure if that's a good thing or not. AFAIK, most of Qt is compatable with the Standard Library. That is, QLT can interoperate with STL, and you can convert back and forth between std::string and Qt::QString, etc. Are there any...
52
3792
by: lovecreatesbeauty | last post by:
Why the C standard committee doesn't provide a standard implementation including the C compiler and library when the language standard document is published? C works on the abstract model of low level machine. C stands for portability and platform and machine independent. If the C compiler and C standard library are written in C itself, is it possible that one "standard" C compiler plus library is enough? The standard implementation is...
24
2456
by: noridotjabi | last post by:
Why isn't there a Graphical User Interface standard? Think about it for a second. You may say, well evey systems API for GUIs is differnt, but do take into acound: every operating system requires differnt compilations and often totally differnt compiler code. For instance gcc on windows in not the same code as gcc on linux/unix but it produces the same programs when you use it to compile. Yes you can take something like: #include...
132
4660
by: Frederick Gotham | last post by:
If we look at a programming language such as C++: When an updated Standard comes out, everyone adopts it and abandons the previous one. It seems though that things aren't so clear-cut in the C community. It would seem that C99 is the most up-to-date Standard, but far more people seem to be working off the C89 Standard. Could someone please explain to me why this is so? --
1
3227
by: manish deshpande | last post by:
Hi, When i'm installing MySQL-server-standard-5.0.24a-0.rhel3.i386.rpm by the following command: rpm -i MySQL-server-standard-5.0.24a-0.rhel3.i386.rpm the following error is being shown: warning: MySQL-server-standard-5.0.24a-0.rhel3.i386.rpm: V3 DSA signature: NOKEY, key ID 5072e1f5 file /etc/my.cnf from install of MySQL-server-standard-5.0.24a-0.rhel3 conflicts with file from package mysql-3.23.58-1 file...
26
3829
by: Rick | last post by:
I'm told that "#pragma once" has made it into the ISO standard for either C or C++. I can't find any reference to that anywhere. If it's true, do any of you have a reference I can use? Thanks...
270
9564
by: jacob navia | last post by:
In my "Happy Christmas" message, I proposed a function to read a file into a RAM buffer and return that buffer or NULL if the file doesn't exist or some other error is found. It is interesting to see that the answers to that message prove that programming exclusively in standard C is completely impossible even for a small and ridiculously simple program like the one I proposed. 1 I read the file contents in binary mode, what should...
0
9646
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9484
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10350
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
10097
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9957
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8983
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7505
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5518
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
3
2887
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.