diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3ac9330a..4b06bcf8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -57,8 +57,8 @@ jobs: - name: Set up JDK uses: actions/setup-java@v3 with: - distribution: 'oracle' - java-version: '17' + distribution: 'zulu' + java-version: '8' - name: Print build environment info run: | @@ -68,7 +68,9 @@ jobs: - name: Build run: | . ./bin/cfglocal.sh - ant -f prj/build.xml -Dextra="-Wno-error" clean build + sed -i "s|-Werror|-Wno-error|g" prj/build-import.xml + git diff + ant -f prj/build.xml clean build # Run unit tests - name: Unit tests diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 28c9dec6..53e4a88b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,68 +1,55 @@ -# Contributing to this repository +# Contributing to Coherence -We welcome your contributions! There are multiple ways to contribute. +Oracle welcomes contributions to this repository from anyone. -## Opening issues +If you want to submit a pull request to fix a bug or enhance an existing +feature, please first open an issue and link to that issue when you +submit your pull request. -For bugs or enhancement requests, please file a GitHub issue unless it's -security related. When filing a bug remember that the better written the bug is, -the more likely it is to be fixed. If you think you've found a security -vulnerability, do not raise a GitHub issue and follow the instructions in our -[security policy](./SECURITY.md). +If you have any questions about a possible submission, feel free to open +an issue too. -## Contributing code +## Contributing to the Oracle Coherence for C++ Community Edition repository -We welcome your code contributions. Before submitting code via a pull request, -you will need to have signed the [Oracle Contributor Agreement][OCA] (OCA) and -your commits need to include the following line using the name and e-mail -address you used to sign the OCA: +Pull requests can be made under +[The Oracle Contributor Agreement](https://www.oracle.com/technetwork/community/oca-486395.html) (OCA). -```text +For pull requests to be accepted, the bottom of your commit message must have +the following line using your name and e-mail address as it appears in the +OCA Signatories list. + +``` Signed-off-by: Your Name ``` -This can be automatically added to pull requests by committing with `--sign-off` -or `-s`, e.g. +This can be automatically added to pull requests by committing with: -```text -git commit --signoff +``` + git commit --signoff ``` -Only pull requests from committers that can be verified as having signed the OCA -can be accepted. +Only pull requests from committers that can be verified as having +signed the OCA can be accepted. -## Pull request process +### Pull request process -1. Ensure there is an issue created to track and discuss the fix or enhancement - you intend to submit. -1. Fork this repository. +1. Fork this repository 1. Create a branch in your fork to implement the changes. We recommend using - the issue number as part of your branch name, e.g. `1234-fixes`. -1. Ensure that any documentation is updated with the changes that are required - by your change. -1. Ensure that any samples are updated if the base image has been changed. -1. Ensure that all changes comply to project coding conventions as documented - [here](DEV-GUIDELINES.md) +the issue number as part of your branch name, e.g. `1234-fixes` +1. Ensure that all changes comply to project coding conventions 1. Ensure that there is at least one test that would fail without the fix and - passes post fix. +passes post fix +1. Ensure that a full verify build passes without **any** test failures 1. Submit the pull request. *Do not leave the pull request blank*. Explain exactly - what your changes are meant to do and provide simple steps on how to validate - your changes. Ensure that you reference the issue you created as well. -1. We will assign the pull request to 2-3 people for review before it is submitted - internally and the PR is closed. - -## Code of conduct - -Follow the [Golden Rule](https://en.wikipedia.org/wiki/Golden_Rule). If you'd -like more specific guidelines, see the [Contributor Covenant Code of Conduct][COC]. - -[OCA]: https://oca.opensource.oracle.com -[COC]: https://www.contributor-covenant.org/version/1/4/code-of-conduct/ +what your changes are meant to do and provide simple steps on how to validate +your changes, ideally referencing the test. Ensure that you reference the issue +you created as well. We will assign the pull request to 2-3 people for review +before it is merged. diff --git a/DEV-GUIDELINES.md b/DEV-GUIDELINES.md deleted file mode 100644 index 16b5de1a..00000000 --- a/DEV-GUIDELINES.md +++ /dev/null @@ -1,581 +0,0 @@ - -# Development Guidelines - -This page provides information on how to successfully contribute to the Coherence C++ extend client. Coding conventions are stylistic in nature and the Coherence style is different to many open source projects therefore we understand the raising of eyebrows. However, consistency is significantly more important than the adopted subjective style, therefore please conform to the following rules as it has a direct impact on review times. - - -## Contents -1. [Coding Guidelines](#intro) - 1. [File Layout and Structure](#1) - 2. [Include Rules](#2) - 3. [Comment Rules](#3) - 4. [Static Constantc and Enums](#4) - 5. [Static data](#5) - 6. [Class conventions](#6) - 7. [Interface conventions](#7) - 8. [Inheritance conventions](#8) - 9. [Memory Management](#9) - 10. [General conventions](#10) - 11. [Finally blocks](#11) - 12. [Indentation conventions](#12) - 13. [Variable declarations and assignments](#13) - 14. [Types](#14) - 15. [Variable prefix conventions](#15) - 16. [Const correctness](#16) - 17. [Exceptions](#17) - 18. [Inner Classes](#18) - 19. [End of file conventions](#19) - 20. [Function implementation conventions](#20) - 21. [Object Model](#21) - 22. [Thread Safety](#22) - 23. [Porting TDE Components to C++ Managed objects](#23) - 24. [Porting Java casts and instanceof checks](#24) - 25. [Right Shift operators](#25) -1. [Tools](#tools) - - -# Coding Guidelines - -The rules below must be adhered to with exceptions being specifically called out to the reviewer. Exceptions to the below rules are exactly that, therefore if an exception is to be presented it must have a compelling justification. - -## File Layout and Structure - -C++ source code is broken into header and implementation files: - -* All header files end in the .hpp suffix. -* All implementation files end in the .cpp suffix. - -### Layout structure - -* All files end at line 78. -* Each class declaration and defiition must be broken up into logical sections. Each section should have the following delimiter: - * Two blank lines - * `// ----- section title --------(out to column 78)` - * Blank line. - * visibility modifier for the section: - -```c++ -// - - - // ----- section title --------------------------------------(out to column 78) - - public: - /** - * First method of the new section (notice no blank line after public:) - */ -``` - -* Classes will generally have the following sections which should be in order as listed (in both .hpp and .cpp files): - * handle definitions - * factory methods - * constructors/destructor - * this interface (methods added by this class) - * parent classes interfaces - * Object interface - * data member accessors - * getters and setters are paired, getter before setter - * inner classes - * constants - * data members - -## Include rules - -* All include files must have standard include header guards. - * The header guard should be the name of the class prefixed with COH and the CamelCase of the name should be switched to use _ (`CAMEL_CASE`). - * The `#endif` for the header guard should have a comment with the header guard name in it - * `coherence/lang.ns` includes all public lang header files. With the exception of the lang package, all header files should include `lang.ns` as the first file in the includes -* All header files must explicitly include the class headers they rely upon, with the exception of `lang.ns`. - * Note: Header files in the lang package must explicitly include the headers in lang they rely upon. **They cannot include lang.ns** -* All namespace nested under the "coherence" namespace automatically pick up a `using namespace coherence::lang` when they include `lang.ns`. This is done to mimic the automatic using of java.lang in Java. This pattern will not be followed for any other namespaces. - * No other namespaces, should be brought in via the "`using namespace`" statement. Rather, explicit "`using class`" statements must be used. - * Two spaces after the last using statement before a class definition. -* Include section rules: - * All includes and using statements must be in alphabetical order. - * Note: `lang.ns` or `compatibility.hpp` should be included first regardless of alphabetical order, and be in its own section (i.e. followed by a blank line). - * Note: In the `.cpp` file, the corresponding header file should be included first regardless of alphabetical order, and be in its own section (i.e. followed by a blank line). - * public and private includes should be in separate sections. -* All classes should be exported via the `COH_EXPORT` macro - -```c++ -#ifndef COH_MY_CLASS_NAME_HPP -#define COH_MY_CLASS_NAME_HPP - -#include "coherence/lang.ns" - -COH_OPEN_NAMESPACE2(coherence,foo) - - -class COH_EXPORT MyClass - { - }; - -COH_CLOSE_NAMESPACE2 - -#endif // COH_MY_CLASS_NAME_HPP -``` - -## Comment rules - -* Comments (and source code) should not exceed past the 78 column point within reason. -* Each class, method and data member must be preceded by a JavaDoc-style comment in the .hpp file. - * Class and method docs should describe functionality and not implementation details. - * If a class method is synchronized there should be a note specifying so in the method comments. - * Data member docs should describe what the data member holds or is used for. - * Comment descriptions should be full sentences ending in a period. - * Parameter descriptions should be two spaces after the parameter name and all be aligned after the longest parameter name. **All parameters must be documented** - * return statements should not start in a capital letter. - * The '\*' at the beginning of each comment line should be found in the first spot directly under the '/' - * Comment structure should consist of: - * Description of the method class or data member - * blank line - * parameters - * return statement -* Doxygen porting rules: - * Don't use html tags that end on their own (`

` for example) - * Make sure your `@param` variables match the ones in the method - * Any reference to `com.tangosol.` must be updated to match a C++ class - * don't use `@link`, doxygen will figure out the links. - -```c++ -/** -* Return a new String comprised of the substring of vsSource -* from iBegin (inclusive) to iEnd (exclusive). -* -* Note: This method is synchronized. -* -* @param vsSource the string to create a substring from -* @param iBegin the starting index from which to create the string -* @param iEnd the index of where the substring should stop -* in vsString or -1 for end of string -* -* @return the new substring created from -*/ -``` - -## Static Constants and Enums - -Static consts, and enum values must be named with an all lower case name. This deviates from the traditional all caps style, but was chosen to try to avoid name collisions with Microsoft's macro names, which don't follow best practices of adding a macro name prefix. Note that Coherence macros are the only thing expressed in all upper case, and they must be `COH_` prefixed. - -## Static data - -Due to the static initialization order [fiasco](http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.12) the coherence C++ API will make no use of static variables including: - -* non-const static data members - * const static data members **must** be declared in the header -* file local static variables -* function local statics (see exception below) - -For non integral types such as Handles, a function local static can be used to circumvent the fiasco. The solution also requires the use of `COH_STATIC_INIT` to ensure thread safety: - -* Bad - * header -```c++ - static const String::Handle EMPTY_STRING; // UNSAFE -``` - * .cpp -```c++ - String::Handle foo::EMPTY_STRING = ""; // UNSAFE -``` -* Good - * .cpp -```c++ - static String::Handle getEmptyString() - { - static String::Handle hEmpty = ""; - return hEmpty; - } - COH_STATIC_INIT(getEmptyString()); -``` - -## Class conventions - -* Classes should be implemented as managed objects by virtually inheriting from `coherence::lang::Object` - * if non-managed objects are created, they should only be stack allocated (no pointers please) -* All methods should be declared virtual. Even if virtual is implied (inherited) it must still be written explicitly. -* Where possible use default parameters to avoid multiple method implementations. -* All classes must have: - * Protected copy constructor. - * The parameter name should be that. - * Protected constructor beyond the copy constructor - make a default constructor if you have no others. - * In the Coherence Object model the copy constructor is coupled with the clone() implementation (see below), and if implemented must be a deep copy - * If class will not support clone() then it will not support the copy constructor. In this case the copy constructor should be declared private and have no implementation. - * Protected virtual destructor. - * No assignment operators. - * Static create method(s) that proxy protected constructors - * Handle/View typedefs (see Object model discussion below) - * Reasonable toString implementation - * Real clone implementation (can simply call the copy constructor) - * As stated in the documentation for clone() on Object, if implemented clone() must return a deep copy such that any changes to the original object will not be visible from the cloned object. Shallow clone() implementations are not allowed, if needed it should be provided via a seperate method, for example an additional create() method. - * By convention clone() is implemented by simply delegating to the classes copy constructor. This means that the copy constructor must be implemented to perform a deep copy. - * In the rare occasion that an object should not be cloned it should not even declare the clone() method in its header, and simply use the implementation provided by AbstractObject. This default implementation throws CloneNotSupportedException. - * For thread safety class data members in general should either be MemberHandle's or MemberViews. In the rare cases where you have a const reference you can use a const Handle or View instead. - * For thread safety, writing to a data member requires synchronization or a field level write lock. -* Any enum in a header file must have the values explicitly set. - -## Interface conventions - -* All interfaces must have: - * virtual inheritance from `coherence::lang::Object` - * Handle/View typedefs (see Object model discussion below). - * Protected empty (i.e {}) virtual destructor. - * Note the protected virtual destructors serve two purposes: To ensure that deleting all objects is restricted, as well as to guarantee that destructors are called in the proper order as classes are extended. - * Pure virtual methods (i.e. = 0 suffix) - * Marker interfaces (i.e. interfaces without any methods) must additionally have a protected empty default constructor and protected empty copy constructor. - -## Inheritance conventions - -The following rules apply to how objects should inherit from base classes: - -* Always inherit Object virtually. -* Always inherit interfaces virtually (interfaces are pure virtual and must have an empty constructor). -* Avoid virtual inheritance except for the above two use cases. - -## Memory Management - -* The Coherence Object model should remove the need for manual memory management in almost all cases. -* pointers and C++ references (including pass by reference) should be avoided - * even when it would be more efficient, more C++ like, and safe to do use them, they should still be avoided - * the coherence::lang package does however make use of these features to build up the object model -* WeakHandle/WeakView must be used when objects have a bidirectional relationship - * by convention the parent holds a strong link to the child, and the child a weak to the parent -* From a language perspective it is generally not safe to store off a pointer to "this" during object construction. Related to that it is unsafe to create Handles/Views to an Object under construction, doing so will result in the Object being destroyed before the constructor returns. The only time this would not occur is if the created Handle/View to "this" outlived the constructor, but even then it is ill advised as the any operations which occurred though the Handle/View would be against a partially construction Object. The need to create a Handle/View to "this" during construction most often arrises due to calling helper methods which happen to use COH\_SYNCHRONIZEd (which creates a new View), or as part of some registration logic, where the new Object gets linked into a larger hierarchy. In any case creating Handles/Views during construction should absolutely be avoided. The Object model borrows from the TDE component model and includes support for a pair of onInit() event methods (one const one not). These methods are called automatically just after the constructor returns, this is done by Object.cpp itself, not the derived classes create methods. When onInit() is called there is already an attachment to the Object, and thus it is safe to create new ones, and also the Object is guaranteed to have been fully constructed. Any logic which relies on references to "this" should be moved into the onInit methods. The only exception to the "this" rule, is that MemberHandles/Views/Holders take \*this in their constructor, this is "safe" as they only rely on the base Object itself to have been initialized, and not the derived class. See the documentation in `Object.hpp` for more details on the usage of onInit(). -* Destructors on managed Objects are very rare, as all data members should either be primitive or managed as well, so there is nothing to delete/free/release manually. In cases where destructor are needed, it is not allowable to create a handle to the destructing Object from within the destructor, any attempt to do so will result in a NULL handle. - -## General conventions - -* Except for template classes, header files must not contain in-lined methods definitions -* The definition of "helper macros" in header files is discouraged, these should be defined in `utility.hpp` -* Method parameters and return values should be primitive or handle/views. In all cases they should be **passed by value**. Pass by reference will not be used, except where required by the language (i.e. copy constructor signature). -* The private visibility modifier **should not** be used, protected should be used instead. -* Data members should always be declared as protected. -* The **NULL** macro is to be used for all "null pointers". 0 should never be used. -* All data members should be prefixed with m\_ -* `public const static` members need not be have a prefix and should be in all caps. -* if, while, and catch should have a space between the statement and the parenthesis (ex: `if ()`) - -## Finally blocks - -C++ does not have finally blocks and as such, code must be duplicated to ensure that cleanup bits are executed properly. In order to simplify the way code looks a cleanup helper class called Finally should be implemented. - -```c++ -namespace - { - struct CloseFinally - { - CloseFinally() - : nSomeState(0) - { - } - - ~CloseFinally() - { - // cleanup code goes here - if (NULL != vResource) - { - // resource specific cleanup - vResource->free(nSomeState); - } - } - - Resource::View vResource; - int nSomeState; - } - } - -void Foo::close() - { - // unprotected code .... - - { - CloseFinally finally; // must be below the curly brace - // protected code - finally.nSomeState = 123; - try // try/catch block not required, but included to show how to mimic Java try/catch/finally, note finally must be declared outside of try block - { - // critical point (update finally state) - Resource::View vResource = acquireFromSomewhere(); - - finally.vResource = vResource; - finally.nSomeState = 456; - } - catch (const SomeException& e) - { - // standard exception processing (happens before finally) - // potentially changes some state of finally - finally.nSomeState = 789; - throw; - } - } // finally destructor runs - - // unprotected code - } -``` - -Note that the CloseFinally helper class breaks most of the rules for Coherence classes. This is because it is not a managed class, not exposed outside the implementation of the Foo class, and most importantly is not accessible to multiple threads. The intention is to write as little code as possible to mimic a Java style finally block. Some notable benefits of the approach are: - -* unnamed namespace, ensuring the the class is only visable from within this file -* helper class occurs immediately before the associated method in the .cpp file, rather then residing in the inner class segment - * this is because it is really just an extension of the method which it helps -* struct used to avoid need to declare items as public -* implemented as a data object, i.e. no accessors methods - * the data members of the helper class are really just an extension of the methods variables -* Also note that there is no reason we couldn't utilize multiple finally classes for a single method, they could even be nested - -## Indentation conventions - -* Each indent consists of 4 spaces (no literal tabs). -* Curly braces are indented from the parent and on their own line. -* Statements that may span multiple lines must be enclosed in braces (e.g. if/for/while/try). This implies that there must never be one or two line if blocks. - -```c++ -if (!vsStr->isASCII()) - { - COH_THROW(UnsupportedOperationException::create("StringHelper utilities only support ASCII strings.")); - } -``` - -## Variable declarations and assignment - -Variable declarations should be aligned such that: -* The types are aligned -* The names are aligned -* The equals operators are aligned -* The assigned values are aligned - -Variable assignments should be aligned such that: -* The names are aligned -* The equals operators are aligned -* The assigned values are aligned - -```c++ -String::View vsText = m_vsFormat; -Array::View vasParameters = m_vasParameters; -``` - -## Types - -* Sized types (e.g. `int32_t`) should be used rather than their un-sized counterparts (e.g. `int`). -* Unsigned types should not be used, except where required by the language. - -## Variable prefix conventions - -* boolean_t -> f -* octet_t -> b -* char -> ch -* size32_t, int32_t -> i (index), n (number), or c (count) -* int64_t -> l (long) -* float32_t -> fl -* float64_t -> dfl -* Object -> v (Object::View), h (Object::Handle), oh (Object::Holder) -* String -> vs (String::View), hs (String::Handle) -* Array -> va (Array::View), ha (Array::Handle) -* Immutable -> ivT (immutable view of type T) -* WeakReferences -> wh(WeakHandle), wv(WeakView) - -## Const correctness - -All code should be const correct (i.e. it is not ok to cast away const-ness even when it is "safe"). - -## Exceptions - -Methods must not have a throws clause, but the JavaDoc-style comments should clearly document what exceptions may be thrown explicitly by the method. - -## Inner classes - -* Inner classes should be fully defined within the scope of the parent class (i.e. `Map::Entry` should be moved within `Map`). -* Inner classes follow the same rules as all other classes (docs, handles, etc.) - -## End of file conventions - -* End all files with a blank line (g++ requirement). - -## Function implementation conventions - -Any object that must be retrieved more than once (either through a reference or accessing a member variable) should be first copied to a local variable. There are two major advantages to this approach: - -* It's more efficient performance wise. -* It's safer with respect to threading. - -```c++ -void Logger::writeMessage(Array::View vaoMsg) - { - int32_t nLevel = cast(vaoMsg->value[1])->getValue(); - String::View vsText = formatMessage(vaoMsg); - Exception::View vEx = cast(vaoMsg->value[3]); - - onLog(); - if (NULL == vEx) - { - m_hLogOutput->log(nLevel, vsText); - } - else if (NULL == vsText) - { - m_hLogOutput->log(nLevel, vEx); - } - else - { - m_hLogOutput->log(nLevel, vEx, vsText); - } - } -``` - -## Object Model - -All objects within the coherence API must conform to the C++ object model outlined below: - -* All objects are managed via a reference count model. Most objects should inherit from AbstractObject which implements everything related to memory management. -* All objects must have factory methods (`create()`) to return Views and Handles. - * A View is a const smart pointer to an object. See the `TypedHandle` class. - * A Handle is a non const smart pointer to an object. See the `Typedhandle` class. - * Handles and Views must be referred to in documentation as "handles". The names of Handle variables must begin with "h". Likewise, the names of View variables must begin with "v". - * The use of `BoxedHandle` (autoboxing) is limited to the `String` class and example code. - * data member Objects are encouraged to be referenced via `MemberHandle`/`MemberViews` - * MemberViews should make use of the corresponding `AbstractObject::onViewedOnly()` event to switch them to Views when the parent becomes only accessible through Views (see WrapperCollections for examples). - * Note that MemberHandle and MemberView will be thread safe whereas View and Handle inherently are not (see below). -* **The use of new is restricted to object factory methods only. Direct access to pointers or references are restricted in the C++ object model** - -## Thread safety - -The Coherence C++ API strives to protect users (and thus our support team) from segfaults and memory corruption as much as possible, without having a large effect on performance. Not all classes within the API need to be thread-safe, but even those which are not thread-safe should still be written in such a way as to help avoid to potential for segfaults/corruption if they are used in a multi-threaded context in an "unsafe" way. For instance our base handle class `TypedHandle` is not thread-safe, that is if one thread assigns it while another thread reads it, there is a possibility that the initially referenced object will be deleted before the accessing thread has a chance to attach to it. Usage of a mutable TypedHandle in a multi-threaded context should therefore be avoided. To do this we've included a few thread-safe implementations of handles. So when should we use the thread-safe handles versus normal TypedHandles? What we've decided is the following: - -* mutable `TypedHandle`s must only be allocated on the stack: - * function/method parameters - * return values - * local variables (i.e. within a function) -* global handles (ick) and data-members handles need to be one of our thread-safe handle implementations: - * MemberHandle - * MemberView - * MemberHolder - * WeakHandle - * WeakView - * WeakHolder - * FinalHandle - * FinalView - * FinalHolder - -When using one of these thread-safe data members within a method you can simply assign it to a normal TypedHandle local variable just as we would do in Java code. - -Since we internally code using our object model the result is that nearly all data structures in the Coherence API are either managed objects or primitives. With these types and the above rules we should end up being fairly well insulated from segfaults/memory corruption even if non thread-safe Objects end up being updated used by multi-threads. This code would certainly be subject to logic type bugs, and could enter and invalid state, but that is no worse then what you would end up with in Java. - -On a related note, primitive data-member fields in C++ are a bit more fragile then in Java. Assume you have two primitive data members which are less then the processor word size. If thread 1 always updates field 1 and thread 2 always updates field 2 we may see logic bugs, because the fields could be packed into the same word, and a write to field 1 could also write back a cached value for field 2 (and vice-versa). Since this would introduce a "logic bug" rather then a segfault it is not worth protecting against for code which is not intended to be used in a multi-threaded context. Code which is intended to be used in a multi-threaded context, must protect against this pattern, even though it would be safe in Java. This can be protected either with full-blown synchronization, or with the lighter weight read/write lock provided by AbstractObject. - -## Porting TDE Components to C++ managed objects - -Almost no one needs to worry about this, but the complex subtleties are easily forgotten: - -* All TDE Components must implement a protected virtual instantiate\*Child\* method for any ported TDE child component. This will allow for component specialization throughout the class hierarchy. -* Porting properties requires three steps: - * Create a private data member for each property - * Create a getter and or setter for each property (matching the visibility from TDE) - * All access to the property should be through these methods - * Set the property's default value in the C++ constructor's initialization list. - * Note by design this does not use the set method. -* Porting TDE's onInit() method requires two steps: - * Start with a verbatim copy of TDE's onInit method. - * At the end of this method you would instantiate each of your children using the virtual instantiate\*Child\* method mentioned above. - -## Porting Java casts and instanceof checks - -The Coherence C++ Object model supports three basic forms of casting for handles/views/holders - -* up casting: i.e. if Bar extends from Foo, casting hBar to hFoo. This will generally happen automatically and no explicit cast operation will be required. In certain rare up-casting cases an explicit cast will be needed. In these cases it is safe to use a Java style cast. i.e. -```c++ - hFoo = (Foo::Handle) hBar; -``` - - Of course in this case the explicit cast operator was not even required. When it most often comes up is in ternaries, consider the following contrived example: -```c++ -Map::Handle createMap(bool fSynchronized) - { - return fSynchronized ? HashMap::create() - : SafeHashMap::create(); - } -``` - - The above will not compile as the ternary operator requires that both expressions result in the exact same type, simply having them derive some the same type is not acceptable. This example could be fixed as follows: -```c++ -Map::Handle createMap(bool fSynchronized) - { - return fSynchronized ? (Map::Handle) HashMap::create() - : (Map::Handle) SafeHashMap::create(); - } -``` - - Note that TypedHandle will ensure that this style cast will only compile if it is safe, so for instance: -```c++ - hBar = (Bar::Handle) hFoo; -``` - - Will not compile, since all Foos are not necessarily Bars. - -* safe down casting: i.e. casting from Bar to Foo. This is achieved using the `cast(Z)`, where X is the class type, Y is Handle/View, and Z is the handle/view/holder to cast. This cast operator is the functional equivalent of a Java down cast, in that it will do a runtime type check, and will throw ClassCastException if the supplied type (Z) is not an instance of (X::Y). -```c++ - hBar = cast(hFoo); // may throw ClassCastException -``` - Note that if Z is `NULL`, then `NULL` will be returned, just as in Java. - -* unsafe down casting: Unlike safe down casting, unsafe down casting will return NULL if the runtime type check fails, rather then throwing ClassCastException. This allows for porting of Java instanceof checks. - -```java -// Java -if (oFoo instanceof Bar) - { - Bar bar = (Bar) oFoo; - bar.someBarMethod(); - } -else - { - // handle non Bar case (including null) - } -``` - ports to -```c++ -// C++ -if (instanceof(hFoo)) - { - Bar::Handle hBar = cast(hFoo); - hBar->someBarMethod(); - } -else - { - // handle non Bar case (including NULL) - } -``` - - alternatively you can use the super secret, doubly efficient cast as an instance of check, by supplying a second parameter of 'false', which will case a failed cast to return NULL rather then throw a ClassCastException. - -```c++ -// C++ -Bar::Handle hBar = cast(hFoo, false); -if (NULL == hBar) - { - // handle non Bar case (including NULL) - } -else - { - hBar->someBarMethod() - } -``` - - Also remember to avoid the down cast operators when up casting, as the run time check is more expensive. - -## Right Shift operators - -In C, the rule for right shifting unsigned types is: - -* The right shift operator will be a logical shift (move to the right and fill with 0). -* For signed types however, it is compiler specific, sometimes it will be arithmetic (preserve the high order bit) and other times it will be logical. - -As such, arithmetic right shifts should be avoided, and all logical shifts when ported should be done using an unsigned type. - -# Tools - -Any C++ editor is currently acceptable provided that it follows the code formatting guidelines below. Eclipse has been chosen as the IDE of choice. diff --git a/README.md b/README.md index 74ffcc70..5439abd3 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,15 @@ ----- - + -[![CI Build](https://github.com/oracle/coherence-cpp-extend-client/workflows/CI%20Build/badge.svg?branch=main)](https://github.com/oracle/coherence-cpp-extend-client/actions?query=workflow%3A%22CI+Build%22+branch%3Amain) +![CI Build](https://github.com/oracle/coherence-cpp-extend-client/workflows/CI%20Build/badge.svg) [![License](http://img.shields.io/badge/license-UPL%201.0-blue.svg)](https://oss.oracle.com/licenses/upl/) # Oracle Coherence for C++ Community Edition @@ -22,34 +22,30 @@ 1. [CLI Hello Coherence Example](#cli-hello) 1. [Programmatic Hello Coherence Example](#prog-hello) 1. [Testing](#testing) -1. [Documentation](https://docs.oracle.com/en/middleware/fusion-middleware/coherence/14.1.2/index.html) +1. [Documentation](https://docs.oracle.com/en/middleware/fusion-middleware/coherence/12.2.1.4/index.html) 1. [Contributing](CONTRIBUTING.md) # Introduction to Coherence -[Coherence](http://coherence.community/) is a scalable, fault-tolerant, cloud-ready, +[Coherence](http://coherence.java.net/) is scalable, fault-tolerant, cloud-ready, distributed platform for building grid-based applications and reliably storing data. The product is used at scale, for both compute and raw storage, in a vast array of -industries such as critical financial trading systems, high performance telecommunication -products and eCommerce applications. +industries including critical financial trading systems, high performance telecommunication +products and eCommerce applications to name but a few. Typically these deployments +do not tolerate any downtime and Coherence is chosen due its novel features in +death detection, application data evolvability, and the robust, battle-hardened +core of the product allowing it to be seamlessly deployed and adapt within any ecosystem. -Typically these deployments do not tolerate any downtime and Coherence is chosen due to its -novel features in death detection, application data evolvability, and the robust, -battle-hardened core of the product that enables it to be seamlessly deployed and -adapted within any ecosystem. - -At a high level, Coherence provides an implementation of the familiar `Map` +At a high level, Coherence provides an implementation of the all too familiar Java `Map` interface but rather than storing the associated data in the local process it is partitioned -(or sharded) across a number of designated remote nodes. This partitioning enables +(or sharded if you prefer) across a number of designated remote nodes. This allows applications to not only distribute (and therefore scale) their storage across multiple processes, machines, racks, and data centers but also to perform grid-based processing -to truly harness the CPU resources of the machines. - -The Coherence interface `NamedCache` (an extension of `Map`) provides methods -to query, aggregate (map/reduce style) and compute (send functions to storage nodes -for locally executed mutations) the data set. These capabilities, in addition to -numerous other features, enable Coherence to be used as a framework for writing robust, -distributed applications. +to truly harness the cpu resources of the machines. The Coherence interface `NamedCache` +(an extension of `Map`) provides methods to query, aggregate (map/reduce style) and +compute (send functions to storage nodes for locally executed mutations) the data set. +These capabilities, in addition to numerous other features, allows Coherence to be used +as a framework to write robust, distributed applications. # How to Get Coherence Community Edition @@ -75,14 +71,14 @@ remote cluster node (over TCP/IP) is completely transparent to the client applic > **_NOTE:_** The C++ client follows the interface and concepts of the Java client, and > users familiar with Coherence for Java should find migrating to Coherence for C++ straightforward. -See [Developing Remote Clients for Oracle Coherence](https://docs.oracle.com/en/middleware/standalone/coherence/14.1.1.0/develop-remote-clients/creating-c-extend-clients.html) +See [Developing Remote Clients for Oracle Coherence](https://docs.oracle.com/en/middleware/fusion-middleware/coherence/12.2.1.4/develop-remote-clients/creating-c-extend-clients.html) for further details. # Building ## Prerequisites -1. A supported hardware platform and C++ compiler. See [Supported Environments for Coherence C++ Client](https://docs.oracle.com/en/middleware/standalone/coherence/14.1.1.0/install/installing-client-distribution.html#GUID-49C698DD-D34A-416D-A71C-566C32824CEA). +1. A supported hardware platform and C++ compiler. See [Supported Environments for Coherence C++ Client](https://docs.oracle.com/en/middleware/fusion-middleware/coherence/12.2.1.4/install/installing-client-distribution.html#GUID-49C698DD-D34A-416D-A71C-566C32824CEA). 1. Oracle Java 8 JDK 1. Apache Ant version 1.7.0 or later 1. [Ant-Contrib](http://ant-contrib.sourceforge.net/) version 1.0b3 @@ -118,7 +114,7 @@ retrieved to illustrate the permanence of the data. 1. The Coherence for C++ shared library see [Building](#build) 1. [Coherence Community Edition](https://github.com/oracle/coherence) coherence.jar - + ## Build Sanka Sanka is a command line tool which can be used to run the `main` method on Coherence C++ classes @@ -341,11 +337,3 @@ files will produce warnings when compiling with GCC cd ../prj/tests/unit (or cd ../prj/tests/functional) ant -Dbuild.type=release build test ``` - -# Contributing - -Interested in contributing? See our contribution [guidelines](CONTRIBUTING.md) for details. - -# Security - -Please consult the [security guide](./SECURITY.md) for our responsible security vulnerability disclosure process diff --git a/SECURITY.md b/SECURITY.md deleted file mode 100644 index fb238413..00000000 --- a/SECURITY.md +++ /dev/null @@ -1,38 +0,0 @@ -# Reporting security vulnerabilities - -Oracle values the independent security research community and believes that -responsible disclosure of security vulnerabilities helps us ensure the security -and privacy of all our users. - -Please do NOT raise a GitHub Issue to report a security vulnerability. If you -believe you have found a security vulnerability, please submit a report to -[secalert_us@oracle.com][1] preferably with a proof of concept. Please review -some additional information on [how to report security vulnerabilities to Oracle][2]. -We encourage people who contact Oracle Security to use email encryption using -[our encryption key][3]. - -We ask that you do not use other channels or contact the project maintainers -directly. - -Non-vulnerability related security issues including ideas for new or improved -security features are welcome on GitHub Issues. - -## Security updates, alerts and bulletins - -Security updates will be released on a regular cadence. Many of our projects -will typically release security fixes in conjunction with the -[Oracle Critical Patch Update][3] program. Additional -information, including past advisories, is available on our [security alerts][4] -page. - -## Security-related information - -We will provide security related information such as a threat model, considerations -for secure use, or any known security issues in our documentation. Please note -that labs and sample code are intended to demonstrate a concept and may not be -sufficiently hardened for production use. - -[1]: mailto:secalert_us@oracle.com -[2]: https://www.oracle.com/corporate/security-practices/assurance/vulnerability/reporting.html -[3]: https://www.oracle.com/security-alerts/encryptionkey.html -[4]: https://www.oracle.com/security-alerts/ diff --git a/bin/cfgcommon.sh b/bin/cfgcommon.sh index a78f36a7..54e3ef03 100644 --- a/bin/cfgcommon.sh +++ b/bin/cfgcommon.sh @@ -3,7 +3,7 @@ # Copyright (c) 2000, 2023, Oracle and/or its affiliates. # # Licensed under the Universal Permissive License v 1.0 as shown at -# https://oss.oracle.com/licenses/upl. +# http://oss.oracle.com/licenses/upl. # # This script sets all environment variables necessary to build Oracle # Coherence for C++ on supported Unix platforms. @@ -107,7 +107,7 @@ fi if [ ! -d "$JAVA_HOME" ]; then if [ $(uname) == "Darwin" ]; then # On OS X can query for JDK location - JAVA_HOME=`/usr/libexec/java_home -v 17 2>&1` + JAVA_HOME=`/usr/libexec/java_home -v 1.8 2>&1` fi fi diff --git a/build_spec.yaml b/build_spec.yaml deleted file mode 100644 index ad014a85..00000000 --- a/build_spec.yaml +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (c) 2022, 2023, Oracle and/or its affiliates. - - version: 0.1 - component: build - timeoutInSeconds: 1000 - shell: bash - - steps: - - type: Command - name: "compress the repo" - command: | - tar -cvzf ${OCI_WORKSPACE_DIR}/repo.tgz ./ - outputArtifacts: - - name: artifact - type: BINARY - location: ${OCI_WORKSPACE_DIR}/repo.tgz \ No newline at end of file diff --git a/include/private/coherence/native/windows/WindowsCondition.hpp b/include/private/coherence/native/windows/WindowsCondition.hpp index c3e0f2ef..53a1f6f6 100644 --- a/include/private/coherence/native/windows/WindowsCondition.hpp +++ b/include/private/coherence/native/windows/WindowsCondition.hpp @@ -1,8 +1,8 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. + * Copyright (c) 2000, 2020, Oracle and/or its affiliates. * * Licensed under the Universal Permissive License v 1.0 as shown at - * https://oss.oracle.com/licenses/upl. + * http://oss.oracle.com/licenses/upl. */ #ifndef COH_WINDOWS_CONDITION_HPP #define COH_WINDOWS_CONDITION_HPP @@ -28,7 +28,7 @@ using namespace coherence::native; * Windows implementation of Condition. * * This implementation utilizes Windows Events which are not subject to the -* spurious wakeup problem. This implementation however can produce spurious +* suprious wakeup problem. This implementation however can produce spurious * wakeups, and users of Condition must account for them. * * @author 2007.12.10 mf @@ -54,7 +54,7 @@ class COH_EXPORT WindowsCondition COH_ENSURE(m_eventEnd != NULL); // TODO - REMOVE THIS STATEMENT - // test if it is an error to reset an unsignaled event + // test if it is an error to reset a unsignaled event // if it is we need to adjust some code COH_ENSURE(ResetEvent(m_eventBegin) != FALSE); } @@ -101,7 +101,7 @@ class COH_EXPORT WindowsCondition << nResult); } - // Note: cleanup order intentionally identical to acquisition order + // Note: cleanup order intetionally identical to acquistion order if (atomicWaiters.adjust(-1) == m_cAllowed) { // all remaining threads are allowed to remain sleeping @@ -144,7 +144,7 @@ class COH_EXPORT WindowsCondition /** * Notify a specific number of threads. * - * @param cThreads the number of threads to notify + * @param cThreads the nubmer of threads to notify */ void notify(bool fNotifyAll) { @@ -171,24 +171,24 @@ class COH_EXPORT WindowsCondition // open by a thread timing out COH_ENSURE(ResetEvent(eventEnd) != FALSE); - // ensure that no thread timed out between these two lines + // ensure that no thread timesout between these two lines m_cAllowed = fNotifyAll ? 0 : cWaiters - 1; int32_t cCurr = atomicWaiters.get(); - // validate that no thread timed out + // validate that no thread timedout if (cCurr == cWaiters) { - // no threads timed out + // no threads timedout break; } else if (cCurr == 0) { - // all waiting threads timed out + // all waiting threads timedout return; } else if (cCurr < cWaiters) { - // some but not all waiting threads timed out + // some but not all waiting threads timedout // try again cWaiters = cCurr; } @@ -209,7 +209,7 @@ class COH_EXPORT WindowsCondition WAIT_OBJECT_0); // though likely already reset by the last thread to wake up - // there is a slight chance that all threads timed out just + // there is a slight chance that all threads timedout just // before we did SetEvent, in which case they could have call // ResetEvent before we did our SetEvent, and we want to ensure // we leave the Event reset diff --git a/include/public/coherence/lang/compatibility.hpp b/include/public/coherence/lang/compatibility.hpp index 452b403b..47e5efa4 100644 --- a/include/public/coherence/lang/compatibility.hpp +++ b/include/public/coherence/lang/compatibility.hpp @@ -85,7 +85,11 @@ #if defined(_MSC_VER) && _MSC_VER >= 1600 # define COH_CC_MSVC // Microsoft Visual C/C++ -# define COH_CC MSVC +# if _MSC_VER == 1900 +# define COH_CC MSVC 2015 // differentiate VS 2015 build +# else +# define COH_CC MSVC +# endif #elif defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x590 # define COH_CC_SUN // Oracle Solaris Studio # if defined (STLPORT) diff --git a/prj/apidoc/api.html b/prj/apidoc/api.html index dda11de4..c1706c68 100644 --- a/prj/apidoc/api.html +++ b/prj/apidoc/api.html @@ -1,11 +1,11 @@ -C++ Client API Reference for Oracle Coherence: +Oracle\u00AE Fusion Middleware C++ API Reference for Oracle Coherence: