Introduction
Coding Covention
- The entire CyberEngineMkIII API is contained within the CYB::API namespace.
- The C++ standard specifies only a public/private default access difference between structs and classes. However, it will always be made explicit in declarations
- Never use struct
- Function/Template arguments will always be prefixed with 'A', the rest of the title will either be descriptive of it's use or the type's distinctive name
- Data structure fields will always be prefixed with 'F', the rest of the title will either be descriptive of it's use or the type's distinctive name
- const will be used wherever possible
- Assert and HCF should be used to check impossible pre/post conditions
- HCF will be optimized as unreachable in release builds
- enum classes should be preferred to regular enums
- Functions where bodies must reside in headers will use .inl files
- Internal translation units and headers are prefixed with CYB
- Data stuctures must specify inheritance access
- Data structures will be laid out in the following order
- Private/Protected/Public
- Fields with varying access for manipulation of type size and CPU caching
- Extended Types
- References
- Pointers
- Standard types in descending size
- Private/Protected/Public
- Static functions
- Default Constructor
- Parameter Constructors (From least to most parameters)
- Copy Constructor
- Move Constructor
- Move Assignment operator
- Destructor
- Pure virtual members
- Virtual members
- Members
- All classes/fields/typedefs/enums must have at least brief documentation
- All functions must have a brief, params, return value, template, exception spec, and thread safety documentation
- Deleted functions are not documented
- Strong typing is used wherever possible
- C++ friending is not used
- References to types will use the lowest possible namespace/class membership prefix
- Virtual inheritance is not used
- std::unqiue_ptrs of types with virtual destructors will be provided to a unit to manage the lifetime of internal objects
- Prefer STL or other containers instead of raw new[]
- Use unique_ptrs to own heap objects
- Use references (If impossible, use standard pointers) to reference objects
- Only use C++ new/delete operators to acquire/release heap memory
- One line if/while/for cases shouldn't use curly braces, with the exception of else(if) abmiguity
- In a switch statement, all enum based cases should be handled or it must contain a default statement
- Functions with no parameters must contain void in their parameter list
- Return types that are not references or pointers must never be const
- Member functions that do not modify object data should be postfixed as const
- Use CYB::API::Threadable for multithreading
Default Constructors and Destructor
The default C++ extended constructors apply. The copy constructor will copy an object verbatim. The move constructor and assignment operator will move the object without affecting it's state. The destructor will clean up an object and may perform other operations as specified
Interop Construction
- Todo:
- Write the interstructors documenatation
RAII and Strong Guarantee
All unit control paths should be able to shut down correctly in the event an exception unwinds the stack. This usually means flagging down and waiting for threads, running IO functions to save any data, and cleaning up owned objects. They should also provide the C++ strong guarantee, meaning that if an exception is throw, data will remain in a valid state. All engine functions provide both these guarantees.
Thread Specification
A function will always note the thread safety of a function or the thread on which a function will run in the case of a callback. The specification types are as follows
Shared Inline
Thread Safety
Callback Thread
Note that function specific documentation overrides what is written here
Thread Safety
This specification is for an engine call that uses an interface class' vtable. It designates which threads can call the function, and at what time
Some common language:
- Can be called from any thread at any time
- There is no issue in calling from multiple threads at the same time
- Can be called from any thread at any time, though return order is not guaranteed
- There is no issue in calling from multiple threads at the same time. However, CyberEngine uses fast locks to sychronize access and, if there is enough traffic in the function, some threads may wait for a long time before executing
- Can only be called from the main thread
- The main thread is defined as the thread that an Application's Run, DedicatedServer, or Invoke call is made. No other thread can call this function
- Access per X instance must be synchronized
- This particular function can be called at the same time for one instance of the target object
- All access must be synchronized for each target instance
- This puts a function into the synchronized group for a class. No two functions in this group can be called at the same time for one instance of the target object
- All access must be synchronized
- No two threads may call this function at the same time
Callback Thread
Functions within this group are usually inlines from the headers or implementations of abstract classes. These document exactly which thread the function will be called from within the engine.
The thread that owns the Context is the thread that had SetupContext called on it for that context. That thread will call this function
Shared Inline
All functions within this group have their sources available in the CyberEngineMkIII headers. A developer can determine the amount of thread safety possible