/*
 * 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.
 */

#ifndef _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_EXPORTABLE_H_  // NOLINT
#define _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_EXPORTABLE_H_

#include "slang_rs_context.h"

namespace slang {

class RSExportable {
 public:
  enum Kind {
    EX_FUNC,
    EX_TYPE,
    EX_VAR,
    EX_FOREACH,
    EX_REDUCE
  };

 private:
  RSContext *mContext;

  Kind mK;

 protected:
  RSExportable(RSContext *Context, RSExportable::Kind K)
      : mContext(Context),
        mK(K) {
    Context->newExportable(this);
  }

 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 deallocation
  // responsibility is then transferred to the object who invoked this function.
  // Return false if the exportable is kept or failed to keep.
  virtual bool keep();
  inline bool isKeep() const { return (mContext == nullptr); }

  inline RSContext *getRSContext() const { return mContext; }

  virtual ~RSExportable() { }
};
}  // namespace slang

#endif  // _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_EXPORTABLE_H_  NOLINT
