//              Copyright (c) 2007 - 2008 Tim Barbour.

#if !defined(Persimmon_H)
#define Persimmon_H

#include <Address.h>
#include <Version.h>
#include <ClassInitialisationException.h>

namespace org { namespace elusion { namespace pmm {
   using klunkxx::Status;
   using klunkxx::Range;
   using klunkxx::Address;
   using klunkxx::Version;
   namespace cd { class PersimmonCD; }
   class Persimmon {
   public:
      static Range<Address> addressSpace();	//+ not implemented yet
      // replaces any previous association with a Persimmon instance and/or per-task state
      static Status createAndUse(const cd::PersimmonCD&);
      static void* root(const char* key);	//+ toy implementation
      static Status beginTrans();		//+ dummy implementation
      static Status endTrans();			//+ semi-implemented - writes dirty pages back to disk
      static void abortTrans();			//+ not implemented yet
      static Status changeConfiguration(const cd::PersimmonCD& neu);	//+ not implemented yet
      static void sever(); 	// severs any existing association with a Persimmon instance and/or per-task state
      static Version version();
      //+ per-task errors etc.
      // PersimmonInitialiser will call these, in user-space, but in kernel-space one must call them explicitly
      static Status classInit();	// idempotent (and thread-safe)
      static void classFini();		// must be called once for every time that classInit has been called
   };
   //+ need PersimmonInitialisationException
   using klunkxx::ClassInitialisationException;
#if !defined(__KERNEL__)
   struct PersimmonInitialiser {
      PersimmonInitialiser() throw(ClassInitialisationException) {
         Status s = Persimmon::classInit();
         if(!s)
            throw ClassInitialisationException("Persimmon", s);
      }
      ~PersimmonInitialiser() throw() { Persimmon::classFini(); }
   };
#if !defined(PMM_NO_INITIALISER_CLASS_IDIOM)
   static PersimmonInitialiser initialisePersimmon;	 // this would not work in kernel-space anyway
#endif
#endif // !defined(__KERNEL__)
}}}

#endif // !defined(Persimmon_H)
