- Recursive spinlock - 3 Updates
- 944 FPS - 2 Updates
- Custom allocator not working with gcc - 17 Updates
- Rust has the same memory problem as C and C++ - 3 Updates
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: May 09 01:55AM +0100 Hi! Today I created a C++ recursive spinlock (based on the spinlock in Boost) and it seems to work! Spinlocks can be a lot faster than the mutexes supplied by the operating system. https://github.com/i42output/neolib/blob/master/include/neolib/mutex.hpp #cpp #gamedev #coding #neoGFX /Flibble -- "Snakes didn't evolve, instead talking snakes with legs changed into snakes." - Rick C. Hodgin "You won't burn in hell. But be nice anyway." – Ricky Gervais "I see Atheists are fighting and killing each other again, over who doesn't believe in any God the most. Oh, no..wait.. that never happens." – Ricky Gervais "Suppose it's all true, and you walk up to the pearly gates, and are confronted by God," Byrne 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." |
Bonita Montero <Bonita.Montero@gmail.com>: May 09 09:49AM +0200 > Today I created a C++ recursive spinlock (based on the spinlock in > Boost) and it seems to work! Spinlocks can be a lot faster than the > mutexes supplied by the operating system. Spinlocks don't make sense in userland because you can't disable the scheduler in userland. The problem here is that a thread holding a spinlock might get de-scheduled and other treads will spin and con- sume CPU-time unutil it gets re-scheduled to relinquish the ownership. |
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: May 09 02:57PM -0700 On 5/9/2020 12:49 AM, Bonita Montero wrote: > the scheduler in userland. The problem here is that a thread holding > a spinlock might get de-scheduled and other treads will spin and con- > sume CPU-time unutil it gets re-scheduled to relinquish the ownership. Mostly true. However, an adaptive lock, that spins a couple of times before it actually blocks can be useful in userland. The PAUSE instruction can help out here. |
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: May 08 02:53PM -0700 On 5/8/2020 2:18 PM, Mr Flibble wrote: > neoGFX achieves 944 FPS: > https://camo.githubusercontent.com/d32e8fabf762b33adbf4f18f447f3530b9b66fd6/687474703a2f2f6e656f6766782e6f72672f74656d702f6c6f6c2e706e673f69643d31 > /Flibble Try out a shader. Something like: https://www.shadertoy.com/view/MdXSWn |
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: May 09 02:54PM -0700 On 5/8/2020 4:23 PM, Mr Flibble wrote: >> https://www.shadertoy.com/view/MdXSWn > neoGFX already has a C++ shader architecture and most of its drawing > primitives use shader code. Okay, well... You are going to have to add a throttle. Say 60 fps is perfect for a game. 944 fps would requite the gamer to smoke caffeine or something. ;^) |
boltar@nowhere.co.uk: May 09 09:50AM Hi Despite having worked with C++ for years I've never bothered with STL custom allocators before. However now I need to. Using some code from various sources I created a very simple custom allocator below which works perfectly in Clang but not in 2 seperate versions of gcc which never call the allocate() or deallocate() functions even though the code compiles fine. I'm sure I've made some stupid error but I can't see what. Can anyone help? Many thanks #include <iostream> #include <memory> #include <vector> #include <string> #include <stdio.h> #include <stdlib.h> using namespace std; template<typename T> class myallocator: public allocator<T> { public: T *allocate(size_t cnt, const void *hint=0) { T *ptr; size_t bytes; bytes = cnt * sizeof(T); printf("Allocating %ld instances, %lu bytes\n",cnt,bytes); ptr = (T *)malloc(bytes); printf("Pointer = %lu\n",(u_long)ptr); return ptr; } void deallocate(T *ptr, size_t cnt) { printf("Deallocating pointer %lu\n",(u_long)ptr); free(ptr); } }; int main() { puts("Creating vector..."); vector<int,myallocator<int> > v; v.push_back(1); v.push_back(2); v.push_back(3); cout << "-----\n"; // String uses built in array for small strings puts("Creating string..."); basic_string<char,char_traits<char>,myallocator<char> > s = "12345"; puts("Appending string..."); // This will force allocation s += "6789012345678901234567890"; puts("End"); return 0; } |
Ian Collins <ian-news@hotmail.com>: May 09 10:22PM +1200 > deallocate() functions even though the code compiles fine. I'm sure I've made > some stupid error but I can't see what. Can anyone help? > Many thanks Your code as posted won't compile (the string construction). In short, don't derive from std::allocator! Also, don't mix iostreams with C stdio. > using namespace std; > template<typename T> > class myallocator: public allocator<T> class myallocator > { > public: using value_type = T; > T *allocate(size_t cnt, const void *hint=0) T *allocate(size_t count) -- Ian. |
Juha Nieminen <nospam@thanks.invalid>: May 09 10:29AM > but not in 2 seperate versions of gcc which never call the allocate() or > deallocate() functions even though the code compiles fine. I'm sure I've made > some stupid error but I can't see what. Can anyone help? The problem seems to be that you are inheriting from std::allocator. I'm not exactly sure why, but it may well be that the library implementation is doing some kind of shortcut if the allocator is of type std::allocator. You can fix it by not inheriting from std::allocator. Simply remove that inheritance and add this to your class: using value_type = T; > printf("Allocating %ld instances, %lu bytes\n",cnt,bytes); You should be using "%zu" for std::size_t type values. > printf("Pointer = %lu\n",(u_long)ptr); No such thing s "u_long". And you probably want to use "%p" for pointers. |
Juha Nieminen <nospam@thanks.invalid>: May 09 10:31AM > Also, don't mix iostreams with C stdio. As long as they are synced (which is possible via standard library) it becomes merely a question of program design rather than validity. |
boltar@nowhere.co.uk: May 09 10:44AM On Sat, 9 May 2020 22:22:49 +1200 >> some stupid error but I can't see what. Can anyone help? >> Many thanks >Your code as posted won't compile (the string construction). It compiles fine on 3 unix compilers. I'm guessing you're using VC++. >In short, don't derive from std::allocator! Also, don't mix iostreams >with C stdio. There's nothing wrong with mixing iostreams with C stdio and there hasn't been for years. |
boltar@nowhere.co.uk: May 09 10:47AM On Sat, 9 May 2020 10:29:34 -0000 (UTC) >implementation is doing some kind of shortcut if the allocator is >of type std::allocator. >You can fix it by not inheriting from std::allocator. Simply remove Ok, but thats what every single code example does. >that inheritance and add this to your class: > using value_type = T; What about in C++98? >> printf("Pointer = %lu\n",(u_long)ptr); >No such thing s "u_long". And you probably want to use "%p" for Err, there very much is such a thing as u_long! |
David Brown <david.brown@hesbynett.no>: May 09 04:03PM +0200 > On Sat, 9 May 2020 10:29:34 -0000 (UTC) > Juha Nieminen <nospam@thanks.invalid> wrote: <snip> >> using value_type = T; > What about in C++98? What about it? It's a very long time since 1998. Why not use a more modern C++ version? >>> printf("Pointer = %lu\n",(u_long)ptr); >> No such thing s "u_long". And you probably want to use "%p" for > Err, there very much is such a thing as u_long! No, there isn't - not in standard C++. If you have a typedef for u_long (a silly idea, IMHO, and certainly wrong in this case) then you have it in /your/ program. But it is not a standard type and it needs a definition. |
boltar@nowhere.co.uk: May 09 03:05PM On Sat, 9 May 2020 16:03:32 +0200 >> What about in C++98? >What about it? It's a very long time since 1998. Why not use a more >modern C++ version? Portability and curiosity. Allocators existed then so how was it done? I presume a typedef since using = is just a wheel reinvention of the same thing. >No, there isn't - not in standard C++. If you have a typedef for u_long >(a silly idea, IMHO, and certainly wrong in this case) then you have it >in /your/ program. But it is not a standard type and it needs a definition. Its defined in sys/types.h (or a file included from it) in the header files of every unix compiler I've used. If VC++ doesn't have it then too bad but then to be blunt a compiler that requires non standard nonsense such as stdafx.h is in no position to dictate what is and isn't a silly idea. |
Bo Persson <bo@bo-persson.se>: May 09 05:54PM +0200 > of every unix compiler I've used. If VC++ doesn't have it then too bad but > then to be blunt a compiler that requires non standard nonsense such as > stdafx.h is in no position to dictate what is and isn't a silly idea. The file stdafx.h is part of the support of precompiled headers, and thus totally optional. On the other hand I must have missed that unix system headers are now part of the language. Care to point me at that C++ standard paragraph? Bo Persson |
David Brown <david.brown@hesbynett.no>: May 09 05:57PM +0200 >> What about it? It's a very long time since 1998. Why not use a more >> modern C++ version? > Portability and curiosity. Allocators existed then so how was it done? Portability should not be an issue - how many people will be using your code without access to at least C++11 ? As for curiosity - often in C++, this means "how painful was it to use the old language compared to the newer and easier ways?". > I presume a typedef since using = is just a wheel reinvention of the > same thing. I guess so. "Using" is more flexible and often clearer (IMHO) than typedef, but in a case like this it should not be different. > of every unix compiler I've used. If VC++ doesn't have it then too bad but > then to be blunt a compiler that requires non standard nonsense such as > stdafx.h is in no position to dictate what is and isn't a silly idea. I haven't the slightest thought for VC++, which I have never used - and I am equally against any VC++ or MS header specific and unnecessary types. (I believe some of the MSVC++ headers have lots of silly type defs.) If you have an unsigned long, the name of the type in C++ is "unsigned long". There is rarely any advantage of have a typedef that gives you nothing else (as distinct from typedefs like uint64_t) - possibly there are situations where it is convenient for the type name to be a single word. This is not such a case. It may be the case that "u_long" is defined in sys/types.h in every *nix toolchain /you/ have used (and it is defined on my Linux system). But it is not standard C++, and not even standard POSIX. It is not necessarily defined in other systems (C++ is used on far more than just Unix and Windows). And your code does not include <sys/types.h>. The appropriate choice of type for printf for a pointer is "%p" and type "void*". If you really want to cast a pointer to an integer type, the type to use is "uintptr_t" - that type /is/ standard, and will be available on any C++ compiler (in theory it requires C++11, in practice any C++ compiler), and it will be the correct size for pointers - something that does not always apply to "unsigned long". |
boltar@nowhere.co.uk: May 09 04:16PM On Sat, 9 May 2020 17:54:49 +0200 >thus totally optional. >On the other hand I must have missed that unix system headers are now >part of the language. Care to point me at that C++ standard paragraph? An earlier poster stated there was no such thing as u_long. Its a standard posix typedef. I'm not going to stick to "pure" c++ when I'm writing unix code even if its test code, otherwise I'd have to throw process control, networking and half a dozen other subsystems which "pure" c++ doesn't support out the window. Any more stupid questions? |
boltar@nowhere.co.uk: May 09 04:23PM On Sat, 9 May 2020 17:57:57 +0200 >> Portability and curiosity. Allocators existed then so how was it done? >Portability should not be an issue - how many people will be using your >code without access to at least C++11 ? As for curiosity - often in Plenty of old systems in companies have old compilers. A company I worked for until 2019 was still on C++ 2003. Calls to upgrade fell on deaf ears. >nothing else (as distinct from typedefs like uint64_t) - possibly there >are situations where it is convenient for the type name to be a single >word. This is not such a case. Each to their own. unsigned long is long winded, u_long is short and to the point and standard on unix. >necessarily defined in other systems (C++ is used on far more than just >Unix and Windows). And your code does not include <sys/types.h>. It doesn't need to - its included by stdlib.h >available on any C++ compiler (in theory it requires C++11, in practice >any C++ compiler), and it will be the correct size for pointers - >something that does not always apply to "unsigned long". Give somes example architectures when it wouldn't apply? |
Ben Bacarisse <ben.usenet@bsb.me.uk>: May 09 08:30PM +0100 >>any C++ compiler), and it will be the correct size for pointers - >>something that does not always apply to "unsigned long". > Give somes example architectures when it wouldn't apply? 64-bit MS Windows systems usually have a 32-bit long. -- Ben. |
Christian Gollwitzer <auriocus@gmx.de>: May 09 09:50PM +0200 >> any C++ compiler), and it will be the correct size for pointers - >> something that does not always apply to "unsigned long". > Give somes example architectures when it wouldn't apply? The most famous is 64 bit Windows. Pointers are 64 bit - as expected - but long is 32 bit. So casting a pointer to unsigned long looses half of the information. https://en.wikipedia.org/wiki/64-bit_computing#64-bit_data_models Christian |
Keith Thompson <Keith.S.Thompson+u@gmail.com>: May 09 02:17PM -0700 >>> On Sat, 9 May 2020 16:03:32 +0200 >>> David Brown <david.brown@hesbynett.no> wrote: >>>> On 09/05/2020 12:47, boltar@nowhere.co.uk wrote: [...] >>On the other hand I must have missed that unix system headers are now >>part of the language. Care to point me at that C++ standard paragraph? > An earlier poster stated there was no such thing as u_long. There is no such thing in standard C++ (unless you define it yourself). Saying there is no such thing is at worst slightly imprecise. > Its a standard > posix typedef. Then you should be able to cite where POSIX specifies it. (I just checked. It doesn't.) Yes, it's defined in <sys/types.h> on some systems. On my Ubuntu system, I see this in /usr/include/bits/types.h : /* Convenience types. */ typedef unsigned char __u_char; typedef unsigned short int __u_short; typedef unsigned int __u_int; typedef unsigned long int __u_long; and <sys/types.h> defines, among other things: typedef __u_long u_long; Personally, I fail to see what's convenient about them. "unsigned long" is a standard type and is completely portable to any conforming C++ (or C) implementation. Using the name "u_long" adds no information. If it's defined as "unsigned long" it's not useful. If it's defined as some other type it's misleading. (I'm mildly curious why those headers define those typedefs. There are probably historical reasons.) Typedefs that provide some information about how a type is used and/or that can be defined differently on different implementations (like size_t and time_t, for example) are useful. Typedefs that simply provide shorter names for existing types are not, in my opinion. > code even if its test code, otherwise I'd have to throw process control, > networking and half a dozen other subsystems which "pure" c++ doesn't support > out the window. Sure, you can write gratuitously non-portable code if you like. Nobody will stop you. But you can expect criticism for it. To be clear, I don't object at all to using non-portable constructs in non-portable code *if there's a valid reason for it*. Do you have some reason to prefer writing "u_long" over "unsigned long"? > Any more stupid questions? Be less rude. -- Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com Working, but not speaking, for Philips Healthcare void Void(void) { Void(); } /* The recursive call of the void */ |
Ian Collins <ian-news@hotmail.com>: May 10 09:21AM +1200 On 09/05/2020 22:31, Juha Nieminen wrote: >> Also, don't mix iostreams with C stdio. > As long as they are synced (which is possible via standard library) > it becomes merely a question of program design rather than validity. They weren't here. I'm happy the that bit of advice is generally valid. The nonsense arguments that followed about format specifiers would have been avoided if he'd just use iostreams! -- Ian |
Ian Collins <ian-news@hotmail.com>: May 10 09:26AM +1200 >>> Many thanks >> Your code as posted won't compile (the string construction). > It compiles fine on 3 unix compilers. I'm guessing you're using VC++. It needed -std=c++17 to compile with gcc and clang. I don't use windows. >> with C stdio. > There's nothing wrong with mixing iostreams with C stdio and there hasn't been > for years. If, as Juha pointed out, they are synchronised. -- Ian. |
Tim Rentsch <tr.17687@z991.linuxsc.com>: May 09 03:22AM -0700 > This is some serious feature creep. Do you realize you have just > casually invented a new not yet existing language, following a > complicated set of rules mixed up from two existing languages? I don't know why you think that's true. It's a simple rule, and the semantics of C is well defined. That said, I acknowledge some of the reservations expressed, and would be happy to consider other ways of providing similar functionality. The important thing is to be able to write an interface that is sure to be understood the same way by both a C compiler and a C++ compiler. How that is expressed is also important, but secondary to having some way to get it done. > It would need a 10-year language design and standardization effort > to get it non-contradictory and useful, by which time both the > target languages have already evolved away. Is this hyperbole, or overreaction? Surely potential problems could be identified and worked out within a normal 3-year C++ revision cycle. And C evolves more slowly than C++. > Seriously guys, what have you got now with extern "C"? Can't you > accept it's basically just an instruction to the linker, similar > to inline'? I understand -- now -- that it is viewed that way by some people in the C++ community. Unfortunately a major use case -- perhaps /the/ major use case? -- is to allow an interface header for C code to be accepted and compiled by a C++ program, as well as by C programs. Seen from that perspective, how 'extern "C"' works now comes up short. Surely you at least admit that a major use case for 'extern "C"' is to wrap an interface header for some C code so that the C library can be used by a C++ program, right? |
Tim Rentsch <tr.17687@z991.linuxsc.com>: May 09 03:56AM -0700 >> Seriously guys, what have you got now with extern "C"? Can't you accept >> it's basically just an instruction to the linker, similar to 'inline'? > It could be some other keyword [..eg..] _Pure "C". Yes. There are advantages to keep using 'extern "C" { ... }' for this purpose, but certainly there are also some costs so it is reasonable to explore possible alternatives. > But that would require C++ standard to specify by what C standard > rules the _Pure "C" code is compiled Undoubtedly that would be done by the C++ standard referencing a specific version of the C standard, much like what is done now (isn't it?) for C library calls and other connections to standard C. Do you see any problems with that approach? > and how the symbols in _Pure "C" block > interact with symbols outside of it (if at all). This is a good point. We would like to be sure that any dependencies on any outside context have the same meaning when compiled as C++ as they do when compiled as C. The easy first idea is to allow an outside symbol to be used only if it were also declared (or defined) inside a "take this as C" wrapper. Of course, whatever rule is suggested, it's important to try it out and get some experience with it before deciding which rule is adopted. |
Tim Rentsch <tr.17687@z991.linuxsc.com>: May 09 05:56AM -0700 > While interoperability at the level of function signatures > (i.e. linkage) is definitely a must, I don't see much gain at the > level of procedure body. Probably it would help if I explain the experience that prompted my suggestion. Some time ago I wrote a small C library, more for fun than anything else, that turned out to be more useful than I originally expected. Naturally I had already written the .h interface headers so the library could be used conveniently by other C code. When I realized the library's greater usefulness of course I set about modifying the library's headers files so it would be callable from C++. Doing that was more work than I expected. The extra work didn't bother me, but something else came up that did. The interface defines some inline functions. What I discovered is that the rules for inline functions is different in C++ than it is in C: even when an inline function definition is accepted in both languages it doesn't always mean the same thing. Ultimately I decided to remove all the inline function definitions because there was no practical way to be sure how they would work in C++ would be the same as how they work in C. Since then I have discovered many more incompatibilities between C and C++, including both ones that cause compilation errors and ones that are accepted but have different meanings in the two languages. (A recent comp.lang.c++ post I sent recently gives a partial list of those.) When I first started programming in C++ (which was quite a while ago, even before the first C standard) there was very little in C that wasn't exactly the same in C++. Since then that has changed a lot, and to all indications will only get larger as time goes on. The extern "C" construct serves two related but distinct purposes. One purpose is outcall, so C++ code can call functions defined in C. The other purpose is incall, so C code can call functions defined in C++. For incall, extern "C" works pretty well (at least, so I gather). For outcall -- that is, for writing headers that can be compiled either as C or as C++, so C functions can be called either from C or from C++ -- how extern "C" works is not nearly as useful as it is for incall, and even dangerous in some respects. I hope people can understand that my proposal is motivated by a desire to address some problems on the outcall side, without meaning or wanting to adversely affect the other uses. |
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