Skip to content

Create a public C++ API

This is the head issue related to the proposition of a new C++ API.

The main idea is as follow.

PDI::Data_Store:

  • the core of PDI should be a PDI::Data_Store class,
  • an instance of Data_Store is accessible from PDI::Context by a data() member function,
  • the Data_Store class is very similar to a std::unordered_map<std::string, PDI::Weak_Ref>,
  • in addition, it is "observable", i.e. one can register to be notified when references are added/removed in it.

PDI::Weak_Ref/PDI::Shared_Ref/PDI::Shared_R_Ref/PDI::Shared_RW_Ref

  • the PDI::Shared_Ref/PDI::Weak_Ref classes can be used outside of PDI, they behave similarly to std::shared_ptr/std::weak_ptr,
    • PDI::Weak_Ref/PDI::Shared_Ref can not be directly dereferenced,
    • when dereferenced, PDI::Shared_R_Ref returns a const pointer,
    • when dereferenced, PDI::Shared_R_Ref returns a normal pointer,
  • these references implement locking:
    • PDI::Shared_R_Ref behaves like a std::shared_lock,
    • PDI::Shared_W_Ref behaves like a std::unique_lock,
  • the memory ownership of shared_ref is weaker than that of shared_ptr (see Java SoftReference):
    • all reference types offer a release() member function similarly to std::unique_ptr,
    • the reclaim() variant release all reference to the exception of the current one,
    • all reference types offer a callback mechanism to be notified before the referenced data is released,
  • unlike their C++ counterpart, these references offer dynamic typing
    • a type() member function is offered that returns a Datatype to retrieve the type information,
    • templated versions are offered so that the user doesn't have to cast the void* pointer on every use,
  • TODO: add a word about metadata & type template system

g_user_ref:

  • the unordered_map<string, std::unique_ptr<Ref_holder>> g_user_ref global variable stores the user-side references of the C API users,
  • Ref_holder is a base class that is specialized with versions holding any of PDI::Weak_Ref/PDI::Shared_Ref/PDI::Shared_R_Ref/PDI::Shared_RW_Ref,
  • Ref_holder can always be converted to a PDI::Weak_Ref.

The C API behaviour is as follow:

  • share creates a new reference and stores it both in the global Context and in g_user_ref,
  • access gets a reference from the global Context and store it in g_user_ref,
  • release removes the reference from g_user_ref,
  • reclaim calls release() on the reference from g_user_ref and removes it.

In other words

void* my_data = //...

// this
PDI_share("name", ptr, PDI_INOUT);
// is equivalent to this
Shared_RW_Ref my_ref(ptr);
pdi.data["name"] = my_ref;

// and this
PDI_release("name");
// is equivalent to this
my_ref.~Shared_RW_Ref(); //< usually done automatically

and

// this
PDI_access("name", *ptr, PDI_INOUT);
// is equivalent to this
Shared_RW_Ref my_ref = pdi.data["name"];

// and this
PDI_reclaim("name");
// is equivalent to this
my_ref.reclaim();
// or this
ptr = my_ref.release();
Edited by Julien Bigot
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information