Implement one-definition-rule (ODR) feature.
When compiling multiple RS files, we say two RS files A and B break ODR
iff:
1. They have at least one common struct named [S] and [S] will be reflected
to ScriptField_[S].java, and
2. [S] defined in A is not *exactly the same* (number of fields, field
type and field name) as the one defined in B.
This CL detects such error.
diff --git a/Android.mk b/Android.mk
index 05066e5..0a8dc14 100644
--- a/Android.mk
+++ b/Android.mk
@@ -202,6 +202,7 @@
slang_rs_context.cpp \
slang_rs_pragma_handler.cpp \
slang_rs_backend.cpp \
+ slang_rs_exportable.cpp \
slang_rs_export_type.cpp \
slang_rs_export_element.cpp \
slang_rs_export_var.cpp \
diff --git a/llvm-rs-cc.cpp b/llvm-rs-cc.cpp
index afd99b4..955d7c6 100644
--- a/llvm-rs-cc.cpp
+++ b/llvm-rs-cc.cpp
@@ -365,8 +365,9 @@
std::list<std::pair<const char*, const char*> > IOFiles;
std::list<std::pair<const char*, const char*> > DepFiles;
- llvm::OwningPtr<SlangRS> Compiler(new SlangRS(Opts.mTriple, Opts.mCPU,
- Opts.mFeatures));
+ llvm::OwningPtr<SlangRS> Compiler(new SlangRS());
+
+ Compiler->init(Opts.mTriple, Opts.mCPU, Opts.mFeatures);
for (int i = 0, e = Inputs.size(); i != e; i++) {
const char *InputFile = Inputs[i];
diff --git a/slang.cpp b/slang.cpp
index cd3cf93..98610c6 100644
--- a/slang.cpp
+++ b/slang.cpp
@@ -185,6 +185,7 @@
mDiagClient = new DiagnosticBuffer();
// This takes the ownership of mDiagClient.
mDiagnostics->setClient(mDiagClient);
+ initDiagnostic();
return;
}
@@ -272,11 +273,15 @@
OT);
}
-Slang::Slang(const std::string &Triple, const std::string &CPU,
- const std::vector<std::string> &Features)
- : mDiagClient(NULL),
- mOT(OT_Default) {
+Slang::Slang() : mInitialized(false), mDiagClient(NULL), mOT(OT_Default) {
GlobalInitialization();
+ return;
+}
+
+void Slang::init(const std::string &Triple, const std::string &CPU,
+ const std::vector<std::string> &Features) {
+ if (mInitialized)
+ return;
createDiagnostic();
llvm::install_fatal_error_handler(LLVMErrorHandler, mDiagnostics.getPtr());
@@ -285,6 +290,8 @@
createFileManager();
createSourceManager();
+ mInitialized = true;
+
return;
}
diff --git a/slang.h b/slang.h
index 96a1390..ea33567 100644
--- a/slang.h
+++ b/slang.h
@@ -71,6 +71,8 @@
} OutputType;
private:
+ bool mInitialized;
+
// The diagnostics engine instance (for status reporting during compilation)
llvm::IntrusiveRefCntPtr<clang::Diagnostic> mDiagnostics;
// The clients of diagnostics engine. The ownership is taken by the
@@ -151,8 +153,10 @@
static void GlobalInitialization();
- Slang(const std::string &Triple, const std::string &CPU,
- const std::vector<std::string> &Features);
+ Slang();
+
+ void init(const std::string &Triple, const std::string &CPU,
+ const std::vector<std::string> &Features);
bool setInputSource(llvm::StringRef InputFile, const char *Text,
size_t TextLength);
diff --git a/slang_rs.cpp b/slang_rs.cpp
index b71e904..566071e 100644
--- a/slang_rs.cpp
+++ b/slang_rs.cpp
@@ -24,6 +24,7 @@
#include "slang_rs_backend.h"
#include "slang_rs_context.h"
+#include "slang_rs_export_type.h"
using namespace slang;
@@ -64,6 +65,92 @@
return RSSlangReflectUtils::GenerateBitCodeAccessor(BCAccessorContext);
}
+bool SlangRS::checkODR() {
+ for (RSContext::ExportableList::iterator I = mRSContext->exportable_begin(),
+ E = mRSContext->exportable_end();
+ I != E;
+ I++) {
+ RSExportable *E = *I;
+ if (E->getKind() != RSExportable::EX_TYPE)
+ continue;
+
+ RSExportType *ET = static_cast<RSExportType *>(E);
+ if (ET->getClass() != RSExportType::ExportClassRecord)
+ continue;
+
+ RSExportRecordType *ERT = static_cast<RSExportRecordType *>(ET);
+
+ // Artificial record types (create by us not by user in the source) always
+ // conforms the ODR.
+ if (ERT->isArtificial())
+ continue;
+
+ // Key to lookup ERT in ReflectedDefinitions
+ llvm::StringRef RDKey(ERT->getName());
+ ReflectedDefinitionListTy::const_iterator RD =
+ ReflectedDefinitions.find(RDKey);
+
+ if (RD != ReflectedDefinitions.end()) {
+ const RSExportRecordType *Reflected = RD->getValue().first;
+ // There's a record (struct) with the same name reflected before. Enforce
+ // ODR checking - the Reflected must hold *exactly* the same "definition"
+ // as the one defined previously. We say two record types A and B have the
+ // same definition iff:
+ //
+ // struct A { struct B {
+ // Type(a1) a1, Type(b1) b1,
+ // Type(a2) a2, Type(b1) b2,
+ // ... ...
+ // Type(aN) aN Type(b3) b3,
+ // }; }
+ // Cond. #1. They have same number of fields, i.e., N = M;
+ // Cond. #2. for (i := 1 to N)
+ // Type(ai) = Type(bi) must hold;
+ // Cond. #3. for (i := 1 to N)
+ // Name(ai) = Name(bi) must hold;
+ //
+ // where,
+ // Type(F) = the type of field F and
+ // Name(F) = the field name.
+
+ bool PassODR = false;
+ // Cond. #1 and Cond. #2
+ if (Reflected->equals(ERT)) {
+ // Cond #3.
+ RSExportRecordType::const_field_iterator AI = Reflected->fields_begin(),
+ BI = ERT->fields_begin();
+
+ for (unsigned i = 0, e = Reflected->getFields().size(); i != e; i++) {
+ if ((*AI)->getName() != (*BI)->getName())
+ break;
+ AI++;
+ BI++;
+ }
+ PassODR = (AI == (Reflected->fields_end()));
+ }
+
+ if (!PassODR) {
+ getDiagnostics().Report(mDiagErrorODR) << Reflected->getName()
+ << getInputFileName()
+ << RD->getValue().second;
+ return false;
+ }
+ } else {
+ llvm::StringMapEntry<ReflectedDefinitionTy> *ME =
+ llvm::StringMapEntry<ReflectedDefinitionTy>::Create(RDKey.begin(),
+ RDKey.end());
+ ME->setValue(std::make_pair(ERT, getInputFileName().c_str()));
+
+ if (!ReflectedDefinitions.insert(ME))
+ delete ME;
+
+ // Take the ownership of ERT such that it won't be freed in ~RSContext().
+ ERT->keep();
+ }
+
+ }
+ return true;
+}
void SlangRS::initDiagnostic() {
clang::Diagnostic &Diag = getDiagnostics();
@@ -75,6 +162,16 @@
Diag.setDiagnosticMapping(
clang::diag::ext_typecheck_convert_discards_qualifiers,
clang::diag::MAP_ERROR);
+
+ mDiagErrorInvalidOutputDepParameter =
+ Diag.getCustomDiagID(clang::Diagnostic::Error,
+ "invalid parameter for output dependencies files.");
+
+ mDiagErrorODR =
+ Diag.getCustomDiagID(clang::Diagnostic::Error,
+ "type '%0' in different translation unit (%1 v.s. "
+ "%2) has incompatible type definition");
+
return;
}
@@ -126,11 +223,7 @@
return false;
}
-SlangRS::SlangRS(const std::string &Triple, const std::string &CPU,
- const std::vector<std::string> &Features)
- : Slang(Triple, CPU, Features),
- mRSContext(NULL),
- mAllowRSPrefix(false) {
+SlangRS::SlangRS() : Slang(), mRSContext(NULL), mAllowRSPrefix(false) {
return;
}
@@ -147,8 +240,7 @@
return true;
if (OutputDep && (DepFiles.size() != IOFiles.size())) {
- fprintf(stderr, "SlangRS::compile() : Invalid parameter for output "
- "dependencies files.\n");
+ getDiagnostics().Report(mDiagErrorInvalidOutputDepParameter);
return false;
}
@@ -208,13 +300,29 @@
return false;
}
+ if (!checkODR())
+ return false;
+
IOFileIter++;
}
return true;
}
+void SlangRS::reset() {
+ delete mRSContext;
+ mRSContext = NULL;
+ Slang::reset();
+ return;
+}
+
SlangRS::~SlangRS() {
delete mRSContext;
+ for (ReflectedDefinitionListTy::iterator I = ReflectedDefinitions.begin(),
+ E = ReflectedDefinitions.end();
+ I != E;
+ I++) {
+ delete I->getValue().first;
+ }
return;
}
diff --git a/slang_rs.h b/slang_rs.h
index 6769744..613de76 100644
--- a/slang_rs.h
+++ b/slang_rs.h
@@ -23,10 +23,13 @@
#include <vector>
#include <string>
+#include "llvm/ADT/StringMap.h"
+
#include "slang_rs_reflect_utils.h"
namespace slang {
class RSContext;
+ class RSExportRecordType;
class SlangRS : public Slang {
private:
@@ -35,6 +38,20 @@
bool mAllowRSPrefix;
+ // Custom diagnostic identifiers
+ unsigned mDiagErrorInvalidOutputDepParameter;
+ unsigned mDiagErrorODR;
+
+ // FIXME: Should be std::list<RSExportable *> here. But currently we only
+ // check ODR on record type.
+ //
+ // ReflectedDefinitions maps record type name to a pair:
+ // <its RSExportRecordType instance,
+ // the first file contains this record type definition>
+ typedef std::pair<RSExportRecordType*, const char*> ReflectedDefinitionTy;
+ typedef llvm::StringMap<ReflectedDefinitionTy> ReflectedDefinitionListTy;
+ ReflectedDefinitionListTy ReflectedDefinitions;
+
// The package name that's really applied will be filled in RealPackageName.
bool reflectToJava(const std::string &OutputPathBase,
const std::string &OutputPackageName,
@@ -43,6 +60,8 @@
bool generateBitcodeAccessor(const std::string &OutputPathBase,
const std::string &PackageName);
+ bool checkODR();
+
protected:
virtual void initDiagnostic();
virtual void initPreprocessor();
@@ -57,8 +76,7 @@
public:
static bool IsRSHeaderFile(const char *File);
- SlangRS(const std::string &Triple, const std::string &CPU,
- const std::vector<std::string> &Features);
+ SlangRS();
// Compile bunch of RS files given in the llvm-rs-cc arguments. Return true if
// all given input files are successfully compiled without errors.
@@ -69,7 +87,7 @@
// target>. If @OutputDep is true, this parameter must be given
// with the same number of pairs given in @IOFiles.
//
- // @IncludePaths - User-defined include path.
+ // @IncludePaths - User-defined include paths.
//
// @AdditionalDepTargets - User-defined files added to the dependencies.
//
@@ -79,7 +97,7 @@
//
// @AllowRSPrefix - true to allow user-defined function prefixed with 'rs'.
//
- // @OutputDep - true if output dependecies file.
+ // @OutputDep - true if output dependecies file for each input file.
//
// @JavaReflectionPathBase - The path base for storing reflection files.
//
@@ -96,6 +114,8 @@
const std::string &JavaReflectionPathBase,
const std::string &JavaReflectionPackageName);
+ virtual void reset();
+
virtual ~SlangRS();
};
}
diff --git a/slang_rs_context.cpp b/slang_rs_context.cpp
index 1bd096c..a63b2ad 100644
--- a/slang_rs_context.cpp
+++ b/slang_rs_context.cpp
@@ -282,6 +282,7 @@
E = mExportables.end();
I != E;
I++) {
- delete *I;
+ if (!(*I)->isKeep())
+ delete *I;
}
}
diff --git a/slang_rs_context.h b/slang_rs_context.h
index accd63f..e4e0416 100644
--- a/slang_rs_context.h
+++ b/slang_rs_context.h
@@ -133,6 +133,13 @@
if (E != NULL)
mExportables.push_back(E);
}
+ typedef ExportableList::iterator exportable_iterator;
+ exportable_iterator exportable_begin() {
+ return mExportables.begin();
+ }
+ exportable_iterator exportable_end() {
+ return mExportables.end();
+ }
typedef ExportVarList::const_iterator const_export_var_iterator;
const_export_var_iterator export_vars_begin() const {
diff --git a/slang_rs_export_func.cpp b/slang_rs_export_func.cpp
index f729c12..ba83290 100644
--- a/slang_rs_export_func.cpp
+++ b/slang_rs_export_func.cpp
@@ -112,7 +112,7 @@
return false;
const llvm::StructLayout *ParamTySL =
- mContext->getTargetData()->getStructLayout(ParamTy);
+ getRSContext()->getTargetData()->getStructLayout(ParamTy);
unsigned Index = 0;
for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
@@ -135,7 +135,7 @@
// Check size
size_t T1Size = RSExportType::GetTypeAllocSize(F->getType());
- size_t T2Size = mContext->getTargetData()->getTypeAllocSize(T2);
+ size_t T2Size = getRSContext()->getTargetData()->getTypeAllocSize(T2);
if (T1Size != T2Size)
return false;
diff --git a/slang_rs_export_func.h b/slang_rs_export_func.h
index 868aa4e..dbe46ee 100644
--- a/slang_rs_export_func.h
+++ b/slang_rs_export_func.h
@@ -41,13 +41,11 @@
friend class RSContext;
private:
- RSContext *mContext;
std::string mName;
RSExportRecordType *mParamPacketType;
RSExportFunc(RSContext *Context, const llvm::StringRef &Name)
: RSExportable(Context, RSExportable::EX_FUNC),
- mContext(Context),
mName(Name.data(), Name.size()),
mParamPacketType(NULL) {
return;
@@ -71,7 +69,6 @@
}
inline const std::string &getName() const { return mName; }
- inline RSContext *getRSContext() const { return mContext; }
inline bool hasParam() const
{ return (mParamPacketType && !mParamPacketType->getFields().empty()); }
diff --git a/slang_rs_export_type.cpp b/slang_rs_export_type.cpp
index ca4e188..416cdfa 100644
--- a/slang_rs_export_type.cpp
+++ b/slang_rs_export_type.cpp
@@ -29,6 +29,10 @@
#include "slang_rs_context.h"
#include "slang_rs_export_element.h"
+#define CHECK_PARENT_EQUALITY(ParentClass, E) \
+ if (!ParentClass::equals(E)) \
+ return false;
+
using namespace slang;
/****************************** RSExportType ******************************/
@@ -413,7 +417,6 @@
ExportClass Class,
const llvm::StringRef &Name)
: RSExportable(Context, RSExportable::EX_TYPE),
- mContext(Context),
mClass(Class),
// Make a copy on Name since memory stored @Name is either allocated in
// ASTContext or allocated in GetTypeName which will be destroyed later.
@@ -428,6 +431,18 @@
return;
}
+void RSExportType::keep() {
+ // Invalidate converted LLVM type.
+ mLLVMType = NULL;
+ RSExportable::keep();
+ return;
+}
+
+bool RSExportType::equals(const RSExportable *E) const {
+ CHECK_PARENT_EQUALITY(RSExportable, E);
+ return (static_cast<const RSExportType*>(E)->getClass() == getClass());
+}
+
/************************** RSExportPrimitiveType **************************/
llvm::ManagedStatic<RSExportPrimitiveType::RSObjectTypeMapTy>
RSExportPrimitiveType::RSObjectTypeMap;
@@ -649,6 +664,11 @@
return NULL;
}
+bool RSExportPrimitiveType::equals(const RSExportable *E) const {
+ CHECK_PARENT_EQUALITY(RSExportType, E);
+ return (static_cast<const RSExportPrimitiveType*>(E)->getType() == getType());
+}
+
/**************************** RSExportPointerType ****************************/
const clang::Type *RSExportPointerType::IntegerType = NULL;
@@ -681,6 +701,17 @@
return llvm::PointerType::getUnqual(PointeeType);
}
+void RSExportPointerType::keep() {
+ const_cast<RSExportType*>(mPointeeType)->keep();
+ RSExportType::keep();
+}
+
+bool RSExportPointerType::equals(const RSExportable *E) const {
+ CHECK_PARENT_EQUALITY(RSExportType, E);
+ return (static_cast<const RSExportPointerType*>(E)
+ ->getPointeeType()->equals(getPointeeType()));
+}
+
/***************************** RSExportVectorType *****************************/
const char* RSExportVectorType::VectorTypeNameStore[][3] = {
/* 0 */ { "char2", "char3", "char4" },
@@ -778,6 +809,12 @@
return llvm::VectorType::get(ElementType, getNumElement());
}
+bool RSExportVectorType::equals(const RSExportable *E) const {
+ CHECK_PARENT_EQUALITY(RSExportPrimitiveType, E);
+ return (static_cast<const RSExportVectorType*>(E)->getNumElement()
+ == getNumElement());
+}
+
/***************************** RSExportMatrixType *****************************/
RSExportMatrixType *RSExportMatrixType::Create(RSContext *Context,
const clang::RecordType *RT,
@@ -849,6 +886,11 @@
return llvm::StructType::get(C, X, NULL);
}
+bool RSExportMatrixType::equals(const RSExportable *E) const {
+ CHECK_PARENT_EQUALITY(RSExportType, E);
+ return (static_cast<const RSExportMatrixType*>(E)->getDim() == getDim());
+}
+
/************************* RSExportConstantArrayType *************************/
RSExportConstantArrayType
*RSExportConstantArrayType::Create(RSContext *Context,
@@ -878,6 +920,18 @@
return llvm::ArrayType::get(mElementType->getLLVMType(), getSize());
}
+void RSExportConstantArrayType::keep() {
+ const_cast<RSExportType*>(mElementType)->keep();
+ RSExportType::keep();
+ return;
+}
+
+bool RSExportConstantArrayType::equals(const RSExportable *E) const {
+ CHECK_PARENT_EQUALITY(RSExportType, E);
+ return ((static_cast<const RSExportConstantArrayType*>(E)
+ ->getSize() == getSize()) && (mElementType->equals(E)));
+}
+
/**************************** RSExportRecordType ****************************/
RSExportRecordType *RSExportRecordType::Create(RSContext *Context,
const clang::RecordType *RT,
@@ -966,3 +1020,34 @@
FieldTypes,
mIsPacked);
}
+
+void RSExportRecordType::keep() {
+ for (std::list<const Field*>::iterator I = mFields.begin(),
+ E = mFields.end();
+ I != E;
+ I++) {
+ const_cast<RSExportType*>((*I)->getType())->keep();
+ }
+ RSExportType::keep();
+ return;
+}
+
+bool RSExportRecordType::equals(const RSExportable *E) const {
+ CHECK_PARENT_EQUALITY(RSExportType, E);
+
+ const RSExportRecordType *ERT = static_cast<const RSExportRecordType*>(E);
+
+ if (ERT->getFields().size() != getFields().size())
+ return false;
+
+ const_field_iterator AI = fields_begin(), BI = ERT->fields_begin();
+
+ for (unsigned i = 0, e = getFields().size(); i != e; i++) {
+ if (!(*AI)->getType()->equals((*BI)->getType()))
+ return false;
+ AI++;
+ BI++;
+ }
+
+ return true;
+}
diff --git a/slang_rs_export_type.h b/slang_rs_export_type.h
index 4f067a2..46f94d4 100644
--- a/slang_rs_export_type.h
+++ b/slang_rs_export_type.h
@@ -71,7 +71,6 @@
} ExportClass;
private:
- RSContext *mContext;
ExportClass mClass;
std::string mName;
@@ -137,8 +136,10 @@
static size_t GetTypeAllocSize(const RSExportType *ET);
static unsigned char GetTypeAlignment(const RSExportType *ET);
- const std::string &getName() const { return mName; }
- inline RSContext *getRSContext() const { return mContext; }
+ inline const std::string &getName() const { return mName; }
+
+ virtual void keep();
+ virtual bool equals(const RSExportable *E) const;
}; // RSExportType
// Primitive types
@@ -261,6 +262,8 @@
inline bool isRSObjectType() const {
return ((mType >= DataTypeRSElement) && (mType < DataTypeMax));
}
+
+ virtual bool equals(const RSExportable *E) const;
}; // RSExportPrimitiveType
@@ -288,7 +291,11 @@
public:
static const clang::Type *IntegerType;
+ virtual void keep();
+
inline const RSExportType *getPointeeType() const { return mPointeeType; }
+
+ virtual bool equals(const RSExportable *E) const;
}; // RSExportPointerType
@@ -325,6 +332,8 @@
static llvm::StringRef GetTypeName(const clang::ExtVectorType *EVT);
inline unsigned getNumElement() const { return mNumElement; }
+
+ virtual bool equals(const RSExportable *E) const;
};
// Only *square* *float* matrix is supported by now.
@@ -359,6 +368,8 @@
unsigned Dim);
inline unsigned getDim() const { return mDim; }
+
+ virtual bool equals(const RSExportable *E) const;
};
class RSExportConstantArrayType : public RSExportType {
@@ -387,6 +398,9 @@
public:
inline unsigned getSize() const { return mSize; }
inline const RSExportType *getElementType() const { return mElementType; }
+
+ virtual void keep();
+ virtual bool equals(const RSExportable *E) const;
};
class RSExportRecordType : public RSExportType {
@@ -465,6 +479,9 @@
inline bool isArtificial() const { return mIsArtificial; }
inline size_t getAllocSize() const { return mAllocSize; }
+ virtual void keep();
+ virtual bool equals(const RSExportable *E) const;
+
~RSExportRecordType() {
for (std::list<const Field*>::iterator I = mFields.begin(),
E = mFields.end();
diff --git a/slang_rs_export_var.cpp b/slang_rs_export_var.cpp
index be94cfa..ef5f31d 100644
--- a/slang_rs_export_var.cpp
+++ b/slang_rs_export_var.cpp
@@ -29,7 +29,6 @@
const clang::VarDecl *VD,
const RSExportType *ET)
: RSExportable(Context, RSExportable::EX_VAR),
- mContext(Context),
mName(VD->getName().data(), VD->getName().size()),
mET(ET),
mIsConst(false) {
diff --git a/slang_rs_export_var.h b/slang_rs_export_var.h
index 1f7eefc..c062543 100644
--- a/slang_rs_export_var.h
+++ b/slang_rs_export_var.h
@@ -37,7 +37,6 @@
class RSExportVar : public RSExportable {
friend class RSContext;
private:
- RSContext *mContext;
std::string mName;
const RSExportType *mET;
bool mIsConst;
@@ -51,7 +50,6 @@
public:
inline const std::string &getName() const { return mName; }
inline const RSExportType *getType() const { return mET; }
- inline RSContext *getRSContext() const { return mContext; }
inline bool isConst() const { return mIsConst; }
inline const clang::APValue &getInit() const { return mInit.Val; }
diff --git a/slang_rs_exportable.cpp b/slang_rs_exportable.cpp
new file mode 100644
index 0000000..53ab33d
--- /dev/null
+++ b/slang_rs_exportable.cpp
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "slang_rs_exportable.h"
+
+using namespace slang;
+
+void RSExportable::keep() {
+ // Invalidate associated Context.
+ mContext = NULL;
+ return;
+}
+
+bool RSExportable::equals(const RSExportable *E) const {
+ return ((E == NULL) ? false : (mK == E->mK));
+}
diff --git a/slang_rs_exportable.h b/slang_rs_exportable.h
index c8f360f..c3d0215 100644
--- a/slang_rs_exportable.h
+++ b/slang_rs_exportable.h
@@ -30,10 +30,14 @@
};
private:
+ RSContext *mContext;
+
Kind mK;
protected:
- RSExportable(RSContext *Context, RSExportable::Kind K) : mK(K) {
+ RSExportable(RSContext *Context, RSExportable::Kind K)
+ : mContext(Context),
+ mK(K) {
Context->newExportable(this);
return;
}
@@ -41,6 +45,16 @@
public:
inline Kind getKind() const { return mK; }
+ // When keep() is invoked, mKeep will set to true and the associated RSContext
+ // won't free this RSExportable object in its destructor. The deallcation
+ // responsibility is then transferred to the object who invoked this function.
+ virtual void keep();
+ inline bool isKeep() const { return (mContext == NULL); }
+
+ virtual bool equals(const RSExportable *E) const;
+
+ inline RSContext *getRSContext() const { return mContext; }
+
virtual ~RSExportable() { }
};
}