On Aug 19, 2008, at 2:59 AM, Zeljko Vrba wrote:
On Mon, Aug 18, 2008 at 07:05:10PM -0400, Daryle Walker wrote:
[SNIP]
You tasks IDs are conceptually opaque, why is any external code wanting to mess with them? The external code shouldn't be doing
There are TWO task IDs: one is used by the library (which I also made), and that one _is_ opaque (at least to library clients), it _is_ typedef, and it is not even an integer (it's a pointer). Now, to every created task, I need to assign a positive[*] index (in an application which just uses the library) which is _not_ opaque: the indices are vertex IDs which are in turn used to construct a CSR representation (edge-lists) of a certain graph which is in turn operated on by an external library. (You may remember my earlier post where I proposed that the CSR class from Boost.Graph provides a documented, public way of accessing the raw CSR vectors.) I will call these "other" IDs "task indices" to avoid further confusion.
I could bundle the task index in the task structure and provide a function that takes the task ID and returns the index. This is not satisfactory for several reasons:
- the task library should be general-purpose and lightweight (task indices might not be needed in certain applications) - task indices may be assigned to different policies, which I do not want to hard-code into the library - I do not want to complicate interfaces with optional information (e.g. extra index parameter to task creation -- see 1st point)
Since the library is written in C (well defined ABI across compilers), I can't provide overloaded interfaces. Thus, I have chosen that the task library shall be minimalistic, and that extra information about tasks, where needed, shall be layered in external containers. In this particular application, the choice of the external container (vector) is dictated by a 3rd party library. [TRUNCATE the rest; ask again if it was important]
I think you should consider your design in C++, without thinking about C-compatibility, then go back and think how to make C- compatible analogues of your public concepts. Doing both full design and C-compatibility at the same time is messing you up. Another problem is defining the SEPARATION between tasks, graphs, and vectors. You seem to have mushed the three concepts together. Your points imply that your task ID numbers aren't really per task, but per task & application combination. This means that you should: 1. define some sort of application ID system 2. define mapping (global) object from a task ID (pointer) AND application ID pair to a number ID. This new ID is what get passed to your graph vectors. I think you can use Boost.Multi-Index to create something like Boost.BiMap, to make a tri-map so entering a task ID (pointer), application ID, or new number ID can get you either of the other two data. 3. your new number IDs do _not_ come from the graph vector sizes. Think about what happens if you grab a new ID after removing a non- end element. (The last two elements would have the same ID.) Instead, you have to keep a global with a running next ID count and/ or a std::set of current IDs. 4. the globals I mentioned shouldn't be full-blown public globals, but probably something class-static within factory classes. BTW, how are the graphing structures/functions taking the number IDs from the vectors and getting useful data from them? Callback functions? Is the graphing sub-system encapsulated? Maybe these number ID vectors should be encapsulated as a graph class, with various graphing functions mapping to member functions of the new graph class. -- Daryle Walker Mac, Internet, and Video Game Junkie darylew AT hotmail DOT com