I wasn't able to work on QubLib very much this week, and any work that I did put in went to my data structures. I did some thinking about how the STL and QubLib could work together, but that's a topic for another day when I do something with it. Today, I think I'll talk briefly about a long term goal.
One thing that I'm sure we've all noticed lately is the increase in platforms that are actually making money in today's world. Ten or fifteen years ago, for the most part everything was Windows. If you developed software that was intended to run on Windows you were pretty much guaranteed a large pool of potential customers. However, with the advent of smartphones, the game is a little different now. People still use their PCs, which now may be either a Windows or a Mac. Linux is a viable option, but I just don't ever see it becoming a mainstream operating system like Windows and OS X. However, humor me and imagine that developing for a Linux system is important. That means that you have three desktop platforms that you have to develop for. Then, people go ahead and decide that they want their smartphones to be able to communicate and share data with their desktops. Did I mention that they want to be able to do it regardless of what they're running on the desktop or their smartphone? So, if a smartphone could run Palm OS, Symbian, Android, or iOS, it doesn't matter. All of those should be able to talk with your Windows, OS X, or Linux desktop. If you approach this problem with a system agnostic data transfer approach, then maybe using bluetooth or the internet you can transfer data no problem, but data transfer isn't the real issue. The real issue is software development. How on earth are you supposed to have a system that runs on each of those desktop and smartphone platforms, and then how are you supposed to be able to keep those systems in sync with each other? Oh, and did I mention that the programs have to be written in different languages? Android runs Java, iOS runs Objective-C, and Symbian runs something... I'm not really sure yet which is the most viable option, but right now I think they operate best with Qt C++.
This is a future goal of mine. If a person develops something with QubLib in C++ and they don't use any of the special features of a language that aren't common to other languages, then it really shouldn't be too difficult to do cross-language compilation. That way, a person would be able to develop their software in Java for Android systems, and then push the button and their Objective-C and C++ versions are automatically generated. It's a long shot, but I think it's possible. I know that systems similar to this work on projects like the Unreal Engine used for game development, but those systems force the developer to program in the Unreal Scripting language, and then the system will convert the scripting language to the platform dependent code. Why can't I program in what I'm familiar in? Why can't I develop in C++ and have Java code pop out the other end?
It's days like this that I wish that I didn't have to work for a living. Anyways, that's all for today. Keep coding!
Development on the Side
Saturday, July 9, 2011
Saturday, July 2, 2011
QubLib Continues
Work on QubLib does continue, even if I don't write about it very often. Actually there's been a lot of work going on. I want to write more in my life, which is probably why I've been keeping a journal more thoroughly lately, but I want to keep posting about QubLib too, because I feel it's a really exciting project. Anyways, here's the big thing that I've been working on lately:
Data Structures.
It seems as though I'm destined to work on these forever just because I've changed my design for them so many times, but I think I've finally hit on an architecture that pays off dividends. So, how have I designed them this time around? Let me explain with pictures!
So here's my original data structure design for a LinkedList. It's pretty simple, but that's what I miss about it. I really like the idea of manipulating objects by an explicitly declared interface, and this takes that interface to two different levels: IContainer and IList. I specifically split my interfaces this way because it allows me to share test cases across my data structures. I can talk about that another time, but my test framework works on interfaces, so I can use one set of IContainer test cases on my LinkedList, ArrayList, BinarySearchTree, and anything else that implements the IContainer interface. It's pretty cool and it's saved me a lot of time. Anyways, this was the original design. However, the more I worked with LinkedList and ArrayList, I realized that they shared a bit of code, especially things like checking bounds on the list. So, I decided that they should both inherit from an abstract base class that would implement that functionality and they could use the inherited version.
Tada! ListBase (and several other DataStructureType-Base classes) were born. It was right about this time that I read Effective C++ by Scott Meyers, which I highly recommend to any serious C++ developer. It definitely gave me a more in-depth knowledge of C++. One thing that it also introduced me to was the idea that a class's public interface should be non-overridable by its subclasses and that the functions that a class would override would be protected. I quickly implemented that because I saw the value in pushing error checking higher up the inheritance tree. I don't have it drawn, but a ContainerBase was born out of this design, and it quickly had its own error checking functionality so that by the time a function got down to LinkedList or ArrayList I knew that I had a valid state. It was pretty nice. It led me to discover the dreaded inheritance diamond that gave life to virtual inheritance in C++, but I feel as though I understand that topic now, and I'm once again a happy camper. Then, I began to have some more issues.
I try to test my code with my testing framework that I talked about earlier as much as I can. One caveat with my testing strategies is that I loathe friend classes. I think they're pretty much the devil of computer programming, at least in C++. I don't know if it's my engineering background, but I don't like exceptions to rules, and a friend class is just that: an exception. However, sometimes when you're testing, you really would like to test the internals of a class to make sure that they are working properly. What is a developer to do? One option is to reveal those internals as public functions so that the test code can access and test them, but doesn't that kind of defeat the purpose of making them "internal functions"? I don't want to reveal them on purpose! What's a programmer to do? Enter my latest design strategy:
I call it the crazy-big-and-complicated-architecture-that-is-so-very-nice-but-takes-forever-to-implement data structure pattern! As you can see, the number of classes that I had at the beginning has doubled to get to this structure, but now I can reveal the ArrayList classes to the programmer who will use QubLib and then I can reveal ArrayListImpl to my test cases. ArrayList essentialy defers to ArrayListImpl for everything and it maintains a clean API for a developer to work with. I actually also ended up creating a ContainerBase that functions like ListBase, except on the IContainer level. It's complex, but I think it's worth it. This design also lets me add another class that I cleverly call "List" on the same level as ArrayList and LinkedList. Its sole job is to defer to the fastest default IList data structure in my library. That means that I can swap implementations under the hood, and no one will have to change their code. They'll see an improvement in their library performance just because I changed the backend. I love programming. I was once told that every computer science problem can be solved by just adding another layer of indirection, and boy does that seem to be the case here.
Anyways, that's what I've been working on now. I'm planning on taking this architecture to my smart pointers next and getting a really clean interface there too, and then onto my strings. Lots of work, but I think it'll really pay off once I get this project moving more.
That's all for today. I'll be back next week (hopefully). Keep coding!
Data Structures.
It seems as though I'm destined to work on these forever just because I've changed my design for them so many times, but I think I've finally hit on an architecture that pays off dividends. So, how have I designed them this time around? Let me explain with pictures!
So here's my original data structure design for a LinkedList. It's pretty simple, but that's what I miss about it. I really like the idea of manipulating objects by an explicitly declared interface, and this takes that interface to two different levels: IContainer and IList. I specifically split my interfaces this way because it allows me to share test cases across my data structures. I can talk about that another time, but my test framework works on interfaces, so I can use one set of IContainer test cases on my LinkedList, ArrayList, BinarySearchTree, and anything else that implements the IContainer interface. It's pretty cool and it's saved me a lot of time. Anyways, this was the original design. However, the more I worked with LinkedList and ArrayList, I realized that they shared a bit of code, especially things like checking bounds on the list. So, I decided that they should both inherit from an abstract base class that would implement that functionality and they could use the inherited version.
Tada! ListBase (and several other DataStructureType-Base classes) were born. It was right about this time that I read Effective C++ by Scott Meyers, which I highly recommend to any serious C++ developer. It definitely gave me a more in-depth knowledge of C++. One thing that it also introduced me to was the idea that a class's public interface should be non-overridable by its subclasses and that the functions that a class would override would be protected. I quickly implemented that because I saw the value in pushing error checking higher up the inheritance tree. I don't have it drawn, but a ContainerBase was born out of this design, and it quickly had its own error checking functionality so that by the time a function got down to LinkedList or ArrayList I knew that I had a valid state. It was pretty nice. It led me to discover the dreaded inheritance diamond that gave life to virtual inheritance in C++, but I feel as though I understand that topic now, and I'm once again a happy camper. Then, I began to have some more issues.
I try to test my code with my testing framework that I talked about earlier as much as I can. One caveat with my testing strategies is that I loathe friend classes. I think they're pretty much the devil of computer programming, at least in C++. I don't know if it's my engineering background, but I don't like exceptions to rules, and a friend class is just that: an exception. However, sometimes when you're testing, you really would like to test the internals of a class to make sure that they are working properly. What is a developer to do? One option is to reveal those internals as public functions so that the test code can access and test them, but doesn't that kind of defeat the purpose of making them "internal functions"? I don't want to reveal them on purpose! What's a programmer to do? Enter my latest design strategy:
I call it the crazy-big-and-complicated-architecture-that-is-so-very-nice-but-takes-forever-to-implement data structure pattern! As you can see, the number of classes that I had at the beginning has doubled to get to this structure, but now I can reveal the ArrayList classes to the programmer who will use QubLib and then I can reveal ArrayListImpl to my test cases. ArrayList essentialy defers to ArrayListImpl for everything and it maintains a clean API for a developer to work with. I actually also ended up creating a ContainerBase that functions like ListBase, except on the IContainer level. It's complex, but I think it's worth it. This design also lets me add another class that I cleverly call "List" on the same level as ArrayList and LinkedList. Its sole job is to defer to the fastest default IList data structure in my library. That means that I can swap implementations under the hood, and no one will have to change their code. They'll see an improvement in their library performance just because I changed the backend. I love programming. I was once told that every computer science problem can be solved by just adding another layer of indirection, and boy does that seem to be the case here.
Anyways, that's what I've been working on now. I'm planning on taking this architecture to my smart pointers next and getting a really clean interface there too, and then onto my strings. Lots of work, but I think it'll really pay off once I get this project moving more.
That's all for today. I'll be back next week (hopefully). Keep coding!
Saturday, February 12, 2011
The latest with QubLib
Seriously? Months since my last post? Wow, I must be in school or something. Anyways, despite my lack of blog post updates on my cross-platform library, I have not lacked on working on the library itself. Allow me to explain a few of the things that I've been doing in the past few months:
1. Memory Management - This has been a huge undertaking for me. I recently read a book named Effective C++ by Scott Meyers, which I highly recommend to anyone who is interested in C++ development, which talked about overloading the new and delete operators. It was an interesting idea to me, especially when I put it into the context of a smart pointer that would be able to determine if it was pointing to something that was on the stack or not. With a little fancy overloading and some nifty design, I've successfully created a HeapManager that when given any address, it will tell you whether something is one the heap or not. Cool huh? But the fun doesn't stop there! I decided to create an AllocationManager singleton object that wraps the whole memory management process, so anytime you call new or delete, your code will end up running through the AllocationManager. What's in there? Well, for starters there is an IAllocator object that does two things: AllocateMemory() and DeallocateMemory(). The standard one (called StdAllocator) just uses malloc() and free() like the normal un-overriden new and delete operators do, but with a quick call to AllocationManager::SetAllocator() you can implement your own custom allocator and have your program using it in no time. I have future plans for allowing a user to use different allocators for different types, but I haven't quite gotten around to that. It's a possibility though.
2. Design Patterns - After working with a bunch of singleton objects I finally got sick of rewriting the same code over and over again. I refactored out my singleton code into a single class called Singleton which can be inherited to provide default Singleton functionality to any class. Thank goodness for code reuse!
3. IO - I've started working on file and console input and output. It's a little bit of a pain, but it was coming along smoothly until I wanted a FileReader to be able to point to a FilePtrStream that was on the stack in one function and then one that was on the heap in another function. That's when I went off on the HeapManager trip. Hopefully I can get back to IO soon and put it all behind me.
4. UDP - Before my last post I had gotten TCP operations working for networking, but I hadn't quite figured out UDP. I've gotten it to work. As I was working on the before mentioned IO, I realized that I need to cut a lot of my network code and realize that Network sockets are really just fancy streams that a simple Reader or Writer object could interact with. So, my networking stuff will change again, but I'm hoping that this time it will look really pretty.
5. ThreadSafe - Have you ever been working with a data structure and had that sudden thought, "Uh oh... Is this thing thread safe?" Well, let me put your mind to rest! In QubLib, it's not! None of my data structures are thread safe by default. However, lets say that you created an IList in the following way:
In order to make this newly formed LinkedList thread safe, all you have to do is wrap it in a ThreadSafe function, like so:
And tadaa! It's thread safe now. Some of you may be asking why I don't just make it all thread safe by default? The answer is that I want to give people options. There may be someone who really wants to crank out as much speed as possible, and they just can't afford to have those mutex locks in the code. My first question would be why are they using this library then, but that aside, I still want to provide the options.
I'm sure there are some other little things that I'm missing, but those are the big ones that I've been chugging away on. Right now I'm working on converting my data structures to use a NVI (Non-virtual Interface) design so that all of my public interface error checking can occur in the interface level of the data structure and the rest of the implementation can work off of design by contract principles. There's a lot of future plans I hope to do with this (contractual static flow analysis?), but that's a long way off. For right now, it just helps me fix bugs.
Anyways, that's all for now. Keep coding!
1. Memory Management - This has been a huge undertaking for me. I recently read a book named Effective C++ by Scott Meyers, which I highly recommend to anyone who is interested in C++ development, which talked about overloading the new and delete operators. It was an interesting idea to me, especially when I put it into the context of a smart pointer that would be able to determine if it was pointing to something that was on the stack or not. With a little fancy overloading and some nifty design, I've successfully created a HeapManager that when given any address, it will tell you whether something is one the heap or not. Cool huh? But the fun doesn't stop there! I decided to create an AllocationManager singleton object that wraps the whole memory management process, so anytime you call new or delete, your code will end up running through the AllocationManager. What's in there? Well, for starters there is an IAllocator object that does two things: AllocateMemory() and DeallocateMemory(). The standard one (called StdAllocator) just uses malloc() and free() like the normal un-overriden new and delete operators do, but with a quick call to AllocationManager::SetAllocator() you can implement your own custom allocator and have your program using it in no time. I have future plans for allowing a user to use different allocators for different types, but I haven't quite gotten around to that. It's a possibility though.
2. Design Patterns - After working with a bunch of singleton objects I finally got sick of rewriting the same code over and over again. I refactored out my singleton code into a single class called Singleton which can be inherited to provide default Singleton functionality to any class. Thank goodness for code reuse!
3. IO - I've started working on file and console input and output. It's a little bit of a pain, but it was coming along smoothly until I wanted a FileReader to be able to point to a FilePtrStream that was on the stack in one function and then one that was on the heap in another function. That's when I went off on the HeapManager trip. Hopefully I can get back to IO soon and put it all behind me.
4. UDP - Before my last post I had gotten TCP operations working for networking, but I hadn't quite figured out UDP. I've gotten it to work. As I was working on the before mentioned IO, I realized that I need to cut a lot of my network code and realize that Network sockets are really just fancy streams that a simple Reader or Writer object could interact with. So, my networking stuff will change again, but I'm hoping that this time it will look really pretty.
5. ThreadSafe - Have you ever been working with a data structure and had that sudden thought, "Uh oh... Is this thing thread safe?" Well, let me put your mind to rest! In QubLib, it's not! None of my data structures are thread safe by default. However, lets say that you created an IList in the following way:
IList<int>* intList = new LinkedList<int>();
In order to make this newly formed LinkedList thread safe, all you have to do is wrap it in a ThreadSafe function, like so:
IList<int>* intList = ThreadSafe<int>(new LinkedList<int>());
And tadaa! It's thread safe now. Some of you may be asking why I don't just make it all thread safe by default? The answer is that I want to give people options. There may be someone who really wants to crank out as much speed as possible, and they just can't afford to have those mutex locks in the code. My first question would be why are they using this library then, but that aside, I still want to provide the options.
I'm sure there are some other little things that I'm missing, but those are the big ones that I've been chugging away on. Right now I'm working on converting my data structures to use a NVI (Non-virtual Interface) design so that all of my public interface error checking can occur in the interface level of the data structure and the rest of the implementation can work off of design by contract principles. There's a lot of future plans I hope to do with this (contractual static flow analysis?), but that's a long way off. For right now, it just helps me fix bugs.
Anyways, that's all for now. Keep coding!
Wednesday, September 29, 2010
QubLib Multithreading
This past week was a career fair at Brigham Young University, and so I went and decided to distribute a few resumes. There were the big companies like Microsoft, Apple, Adobe, and others like that, and so I took the chance to drop my name into all of their employment databases. On my resume I have a quick snippet about QubLib. It really isn't all that much, but it is a small bullet point that says that I'm developing a Cross-Platform C++ Library that supports common Data Structures, Networking, Shared Strings, and Multithreading. Multithreading, huh? After the career fair I went back and looked at how far I had gotten on Multithreading in the past month. Not too far. The Windows Thread class could start a thread, but waiting for finish/joining, suspending, and resuming were all features that were on the to do list. Fortunately for me, a week after noticing this I got sick (yesterday), and so what else was I supposed to do while I was sitting in bed all day? I worked on Cross-Platform multithreading. :) So, now QubLib fully supports an inheritable Thread class that can start and wait for finish, a Mutex class, and a Semaphore class. There was a particular joy that swept through me when I got the test cases to work on both Windows and Linux. Fun fun.
Thursday, August 5, 2010
QubLib Distributable
Well, I've been working hard for the past while on QubLib, and today was the first day that I actually build a distributable version. Unfortunately, just because I can build one now, doesn't mean I'm going to distribute it, but it's in the works.
I also just finished working on QubLib Strings. It was a really good experience working on them. I ended up deciding to make them the shared strings like I talked about in an earlier post. They're pretty nice, and hopefully the experience will not have just been for learning purposes.
I also just finished working on QubLib Strings. It was a really good experience working on them. I ended up deciding to make them the shared strings like I talked about in an earlier post. They're pretty nice, and hopefully the experience will not have just been for learning purposes.
Monday, August 2, 2010
QubLib Strings
Strings have been giving me a little bit of a challenge lately. Programming them hasn't been the problem. The problem has been deciding which type of design I want to use.
I've been told that Java uses a design that I will call "Shared Strings". Essentially, if you create the string "hi there" and then somewhere else you create it again, both string references are pointing at the same "hi there" in memory. This is extremely useful in situations where you have 10 bazillion references to "hi there". There is no need to have that same string 10 bazillion times in memory. However, doing it this way does produce a slight overhead problem. I have a StringManager singleton object that keeps track of all of my strings along with how many times they are referenced, very similar to my smart pointer that I introduced a while back. Everytime you create a string, it takes about a log(n) time chunk to see if the string is already in the StringManager. Then upon deletion, it takes another log(n) time chunk to see if the string has any other references. The deletion time is because in an actual String object I am storing a char*, which points to the actual heap-allocated character array in the StringManager. I suppose I could have a String object point to the char* and the integer value that indicates how many references it has. But keeping it the way it is right now is nice because it keeps things simple. What do you think? Are there any other options that I haven't considered yet but should keep in my head? Or, are there other factors that I'm not thinking about that would probably seal the deal for which route I will end up taking?
I've been told that Java uses a design that I will call "Shared Strings". Essentially, if you create the string "hi there" and then somewhere else you create it again, both string references are pointing at the same "hi there" in memory. This is extremely useful in situations where you have 10 bazillion references to "hi there". There is no need to have that same string 10 bazillion times in memory. However, doing it this way does produce a slight overhead problem. I have a StringManager singleton object that keeps track of all of my strings along with how many times they are referenced, very similar to my smart pointer that I introduced a while back. Everytime you create a string, it takes about a log(n) time chunk to see if the string is already in the StringManager. Then upon deletion, it takes another log(n) time chunk to see if the string has any other references. The deletion time is because in an actual String object I am storing a char*, which points to the actual heap-allocated character array in the StringManager. I suppose I could have a String object point to the char* and the integer value that indicates how many references it has. But keeping it the way it is right now is nice because it keeps things simple. What do you think? Are there any other options that I haven't considered yet but should keep in my head? Or, are there other factors that I'm not thinking about that would probably seal the deal for which route I will end up taking?
Thursday, July 29, 2010
QubLib Events
No, I'm sorry. This post is not about a pancake breakfast in honor of QubLib. It's not that type of event. This is about Event objects in associated with Event handling. For the past few days I've been working on getting these objects working and also in getting them tested. The result of my sweat and tears (mostly tears)?
That little bit of code just set up an event, adding a pointer to the function someFunction, and then executed all functions that had been registered with the Event e. It may not be as pretty as I had envisioned it a couple of weeks ago, but it works. At the end of the day, that's what makes me happy.
Event0 e;
e += FunctionPtr0<void>(someFunction);
e();
That little bit of code just set up an event, adding a pointer to the function someFunction, and then executed all functions that had been registered with the Event e. It may not be as pretty as I had envisioned it a couple of weeks ago, but it works. At the end of the day, that's what makes me happy.
Subscribe to:
Posts (Atom)