Jump to content
  • Advertisement

IFooBar

Member
  • Content Count

    1947
  • Joined

  • Last visited

Community Reputation

906 Good

About IFooBar

  • Rank
    Contributor

Personal Information

  1. Hi guys, I'm trying to play around in C++ a bit by making an Either class ala Haskell's. I have the basics working, but I want to be able to call a single "value()" member function of the Either class instead of calling first() when the first value is available and second() when the second value is available. Any hints on how to get that working? So far I have the following: template<class First, class Second> class Either { public: template<class T> Either<First, Second>& operator=(Either<T, Empty> &either) { first_ = either.value(); hasFirst_ = true; return *this; } template<class T> Either<First, Second>& operator=(Either<Empty, T> &either) { second_ = either.value(); hasFirst_ = false; return *this; } bool hasFirst() const { return hasFirst_; } bool hasSecond() const { return !hasFirst_; } const First& first() const { return first_; } const Second& second() const { return second_; } private: union { First first_; Second second_; }; bool hasFirst_; }; template<class First> class Either<First, Empty> { public: Either(const First &first) : first_(first) {} bool hasFirst() const { return true; } bool hasSecond() const { return false; } const First& value() const { return first_; } private: First first_; }; template<class Second> class Either<Empty, Second> { public: Either(const Second &second) : second_(second) {} bool hasFirst() const { return false; } bool hasSecond() const { return true; } const Second& value() const { return second_; } private: Second second_; }; template<class First> Either<First, Empty> makeEitherFirst(const First &first) { return Either<First, Empty>(first); } template<class Second> Either<Empty, Second> makeEitherSecond(const Second &second) { return Either<Empty, Second>(second); } Also I've noticed perfect forwarding features of c++ 11 now, would it be possible to incorporate that in the operator = members of the Either template above. Maybe something like first_ = std::forward(either.value()). But that would require the parameters for the oepartor =() to take && values? I tried doing that but then I had to make the members && values as well, which meant I need to have appropriate default constructors. Anyway to avoid that? Currently this is my test code: Seed::Either<int, float> result; result = Seed::makeEitherFirst(3); std::cout << result.first() << std::endl; // want this to be result.value() instead result = Seed::makeEitherSecond(4.0); std::cout << result.second() << std::endl; // want this to be result.value() instead Thanks for any help!
  2. Well, if you do this write(elem1) // maybe OS fsyncs maybe not write(elem2) // maybe OS fsyncs maybe not ... write(elemN) // maybe OS fsyncs maybe not fsync(); // as opposed to write(entire data block) // maybe OS fsyncs maybe not fsync(); I don't think that's moot since IO is quite expensive. But like I said, maybe memcpy'ing into my own buffer before writing would be a nice middle ground if padding is not guaranteed (or change the structure)
  3. That will just flush the buffers out to the OS, the kernel does it's own buffering as well which can only be flushed with fsync AFAIK. It does prevent less than X bytes of data being written to disk though, at least...
  4. Ah, so there may be padding between members z and a? Or did I misunderstand transitive member? Yeah I am using the compiler's packing attribute. But I want to avoid using it on the entire DataTypeA struct and just use it on the anonymous struct within DataTypeA so that those members are laid out contiguously in memory with the members of BaseData (since that's pragma packed as well). I could also have a packed BaseData followed by a named packed struct DataAHeader (which derives from BaseData) and then followed by struct DataTypeA which contains random types and derived from DataAHeader. But then if transitive members are an issue, maybe not. Re Howerver #2: Writing each members out individually is probably a no go. The target is flash storage and for every write, the disk controllers read a fixed chunk of file space, erase a chunk and then write out the same amount (lets say 4k). So if I wrote member a, then I'd incur a 4k read and a subsequent 4k write, even though member a is 4 bytes. On the other hand there's probably some internal buffering going on, but that's quite unpredictable. And on top of that, you usually wear out flash storage within 10000 writes, so the less and more controlled the better. It is certainly an option to serialize the members in smaller chunks to a 4k buffer myself and then write that to file though. I guess multiple memcpys to my own buffer in memory wouldn't be that much of a hit? I'm not too sure. But also if the padding stuff is guaranteed then might as well use it no.
  5. Hi, If I have a design like: struct BaseData { int x, y, z; } packed; struct DataTypeA : BaseData { struct { int a, b, c; } packed; other types; more other types; }; DataTypeA varA; I'm using this to write stuff to files and what not. Each data type has common header information (BaseData) and then it's own information that needs to be written to file (ie. DataTypeA needs int a, b, c). In the above code, is the first sizeof(int) * 6 bytes of varA, which is of type DataTypeA, guaranteed to have the values of variables x, y, z and a, b, c (in that order)? Thanks!
  6. Thanks for those mentions. Hadn't heard of them before. So they compact the file in a separate thread. That is one option I am looking at but would like to avoid due to dram constraints.
  7. Hi there, this post is kind of long, but it's as far as I know a previously untackled problem (couldn't find any research papers on it or anything) so it might be interesting. The problem is with trying to do garbage collection on an append-only file. This file has pages written to it sequentially, and every now and then, a previous page becomes obsolete so theoretically it can be reused. I have an implementation of a database and it's stored as a b+tree on disk. It's append only so it's never overwritten, which makes it less susceptible to corruption, and provides automatic versioning. A few things about the data structures 1) File writes are carried out in pages of size X (4k default) - depending on disk block size. 2) There are 4 types of pages - head, leaf, branch and meta. The leaf and branch pages are data pages. The head is only written once when you create a file for the first time. 3) All data pages have a page number (this gives easy access - page 4 means it's at offset 4* PageSize in the file on disk). 4) A meta page is written after every data commit. The meta page contains the number of the root data page. 5) Since it's append only, whenever a write happens, all the pages that are affected have to be recreated and appended. Typical process of writing: a) create file: write header page (that's 4k gone, even though header is about 64 bytes or something) b) write first key/value pair (i.e. node): create a new leaf page and store the node in it. Then create a meta page and set it's root page to the new leaf page. ** so now we have 3 pages after one write - head page 0, leaf page 1, meta page 2. c) write another node: find where it goes in tree. There's space in page 1 so copy page 1 and add node to it. Now copy old meta page and set root page to the copy of page 1. ** Now we have 5 pages: head page 0, old leave page 1, old meta page 2, new leaf page 3 and new meta page 4 (which points to root page 3). d) write node that can cause a split. Find where it goes in tree. Start at root (page 3), see that there is no space, so split. ** page 3 turns into page 5 and 6. ** write nodes to page 5 and 6. ** create branch page 7, and create nodes in branch that point to page 5 and 6 ** create new meta page 8 and set root page to branch page 7. So as you can see, there's a lot of space wastage. As meta pages are added and root pages shift, old pages become reusable. So I'm trying to think of ways to flag them as reusable. One way is to mark a page that needs to be copied as garbage. But the problem with that is the write process. While the newest meta page may be at page 75 on disk, a previously opened read transaction might point to a meta page 32 which has a path to leaf page 3 or something. So a big problem is that since older meta pages are not writable, I can't tell it that "all read transitions on you are now closed". One other big gotcha. While the main process has write access to the file. Another process can open it for read access and choose which meta page to open it from, so there's no way to know which meta the other read process is accessing, unless I allow the read process to set markers in the file (but then it violates the read only access). I haven't looked in to it yet, but there's a possibility that linux file systems maybe detach a readonly file if another process starts writing to it. If that is constant then I guess the other process doesn't matter. But that's on my to do list, for now I thought maybe I could pick you guys' brains to see if anyone has dealt with anything similar or has some ideas of how to mark pages and what not. I hope I explained it well enough, and thanks a lot for any input! Cheers.
  8. Problem is you can't partially specialize functions, but you can partially specialize an implementation structure within TFoobar to get what you need template<class T, class U> class TFoobar { public: template <class T, class U> struct func_impl { static void impl(T t, U u) { } }; template <class U> struct func_impl<float, U> { static void impl(float t, U u) { } }; void func(T t, U u) { func_impl<T, U>::impl(t, u); }};
  9. That is quite interesting. So casting src to unsigned char would fix that as I guess? Are you sure? I tried to produce it but for example f dstlen is 3 and srclen is 4 then we: * i = 0 - write src[0] into temp. - add 2 to len (len = 2) - copy temp to dst (dst = "XX\0") * i = 1 - write src[1] into temp - add 2 to len (len = 4); - if statement protects against further copies now. You're right about the user wondering what's what though! First thing I thought of. Exciting things might happen if (src == dst) too, but I haven't checked it to confirm that. [/quote] Those are things I should probably check for.
  10. Thanks! Yeah the temp can be avoided indeed. Entire string doesn't have to be built so that's ok. Assert(dstlen >= 1) it should be. Also, when srclen does include the \0 then that's considered a safer case then when it does not right?
  11. Hi guys, does this code have any safety issues? const char *tohexstr1(const char *src, size_t srclen, char* dst, int dstlen) { assert(dstlen > 1); char temp[3]; int len = 0; *dst = 0; for (size_t i = 0; i < srclen; ++i) { sprintf(temp, "%02X", src); temp[2] = 0; len += 2; if (len < dstlen) strcat(dst, temp); } return dst; } Thanks in advance!
  12. IFooBar

    shared_ptr in VS 2008

    Just by the by, you can also make boost tr1 library behave like it's the standard so that when you #include <memory> in vs08, it will actually include boost/tr1/memory.hpp (makes switching between vs10 and vs08 for example transparent) so maybe that may help convince your teammate as well. See here: http://www.boost.org/doc/libs/1_47_0/doc/html/boost_tr1/usage.html#boost_tr1.usage.include_style
  13. Yeah it works then (also just if you put it in front of B), but then it produces compiler errors somewhere else. Only solution right now is to make wrappers. Aw common dude. I just saw that MS acknowledged my feedback!! I was not monitoring that thing 24/7 you know... :/ And I was not going to post here that the issue was posted there before I was sure it was actually something solid. But yeah it turns out it's a bug in VC and it'll be resolved in the next version. It would be interesting to see what was going wrong on the backend though. Ok, now for that mod dude... Wow that's amazing, I love how you take15 words from a 200 word post of mine and choose to highlight 5 words that completely work against me. Completely! Impressive. Though, the other part of the title which you conveniently ignore reads bug in visual studio 2010. Which also makes it abundantly clear that I thought the problem was in MSVC, not in the code, but since I wasn't a 100% sure, I posted here. Claim? Admit? What? Are we in a court room? I'm not claiming anything (aggressively or otherwise). I was just asking if the code is supposed to produce an error or not. I assumed people would know that you create libraries in different ways depending on the platform - maybe because I don't assume people are morons (as you so eloquently put it). So when I said standard conforming code I was implicitly referring to the actual c++ code (which declspec is not a part of) and wondering if there was anything wrong with it. I can tell from your tone that you're one of those guys who thinks they're always right, but chill out will ya, and do something productive instead of chucking around insults. If you don't mind, I'm going skip the part where I provide a retort to you calling me a dick and a moron since someone has to keep things civil.
  14. Because most people who think they've found a compiler bug are mistaken, and this is a decent place for finding corrections in bad code? [/quote] Exactly... Was looking for someone to just confirm that the code should compile. Rather get some people I trust to confirm it. And this is probably my most trustable forum. And it's pretty interesting behaviour from vc as well. Just wish some people wouldn't nit pick.
  15. Way to miss the point... The point is that the piece of code should not be problematic AFAIK. Unless Im missing something. Use whatever you need to use to export the code in to a library. MSVC uses declspec dllexport. I did not use declspec when compiling with gcc, obviously, since I was not testing out MSVC's specific extension. Though in this case it might be a bug with the way declspec is implemented. Unless (now here's the point of the post) there's something wrong with the code.
  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!