factory.h 9.3 KB
Newer Older
W
wangguibao 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
// Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.
//
// 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.

#pragma once
#include <map>
#include <string>
#include <utility>
G
guru4elephant 已提交
19 20
#include "core/sdk-cpp/include/common.h"
#include "core/sdk-cpp/include/stub_impl.h"
W
sdk-cpp  
wangguibao 已提交
21 22 23 24 25

namespace baidu {
namespace paddle_serving {
namespace sdk_cpp {

W
wangguibao 已提交
26 27 28 29
#ifdef BCLOUD
namespace brpc = baidu::rpc;
#endif

30 31 32 33 34 35 36 37 38 39 40 41 42
#define ERROR_STRING_LEN 10240

#define INLINE_REGIST_OBJECT(D, B, E)                                   \
  do {                                                                  \
    Factory<D, B>* factory = new (std::nothrow) Factory<D, B>();        \
    if (factory == NULL ||                                              \
        FactoryPool<B>::instance().register_factory(#D, factory) != 0) {\
      char err_str[ERROR_STRING_LEN];                                   \
      snprintf(err_str, ERROR_STRING_LEN - 1,                           \
        "Failed regist factory: %s->%s in macro!", #D, #B);             \
      RAW_LOG(ERROR, err_str);                                          \
      return E;                                                         \
    }                                                                   \
W
wangguibao 已提交
43 44
  } while (0)

45 46 47 48 49 50 51 52 53 54 55 56
#define DECLARE_FACTORY_OBJECT(D, B)                                    \
  static int regist(const std::string& tag) {                           \
    Factory<D, B>* factory = new (std::nothrow) Factory<D, B>();        \
    if (factory == NULL ||                                              \
      FactoryPool<B>::instance().register_factory(tag, factory) != 0) { \
      char err_str[ERROR_STRING_LEN];                                   \
      snprintf(err_str, ERROR_STRING_LEN - 1,                           \
        "Failed regist factory: %s in macro!", #D);                     \
      RAW_LOG(ERROR, err_str);                                          \
      return -1;                                                        \
    }                                                                   \
    return 0;                                                           \
W
wangguibao 已提交
57
  }
W
sdk-cpp  
wangguibao 已提交
58 59

#define PDS_STR_CAT(a, b) PDS_STR_CAT_I(a, b)
W
wangguibao 已提交
60 61 62 63 64 65 66 67
#define PDS_STR_CAT_I(a, b) a##b

#define DEFINE_FACTORY_OBJECT(D)                                           \
  __attribute__((constructor)) static void PDS_STR_CAT(GlobalRegistObject, \
                                                       __LINE__)(void) {   \
    D::regist(#D);                                                         \
  }

68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
#define REGIST_FACTORY_OBJECT_IMPL(D, B)                                    \
  __attribute__((constructor)) static void PDS_STR_CAT(GlobalRegistObject,  \
                                                       __LINE__)(void) {    \
    ::baidu::paddle_serving::sdk_cpp::Factory<D, B>* factory =              \
      new (::std::nothrow)::baidu::paddle_serving::sdk_cpp::Factory<D, B>();\
    if (factory == NULL ||                                                  \
      ::baidu::paddle_serving::sdk_cpp::FactoryPool<B>::instance()          \
                .register_factory(#D, factory) != 0) {                      \
      char err_str[ERROR_STRING_LEN];                                       \
      snprintf(err_str, ERROR_STRING_LEN - 1,                               \
        "Failed regist factory: %s->%s in macro!", #D, #B);                 \
      RAW_LOG(ERROR, err_str);                                              \
      return;                                                               \
    }                                                                       \
    return;                                                                 \
W
wangguibao 已提交
83 84
  }

85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
#define REGIST_FACTORY_OBJECT_IMPL_WITH_TAG(D, B, T)                        \
  __attribute__((constructor)) static void PDS_STR_CAT(GlobalRegistObject,  \
                                                       __LINE__)(void) {    \
    ::baidu::paddle_serving::sdk_cpp::Factory<D, B>* factory =              \
      new (::std::nothrow)::baidu::paddle_serving::sdk_cpp::Factory<D, B>();\
    if (factory == NULL ||                                                  \
      ::baidu::paddle_serving::sdk_cpp::FactoryPool<B>::instance()          \
            .register_factory(T, factory) != 0) {                           \
      char err_str[ERROR_STRING_LEN];                                       \
      snprintf(err_str, ERROR_STRING_LEN - 1,                               \
        "Failed regist factory: %s->%s, tag %s in macro!", #D, #B, T);      \
      RAW_LOG(ERROR, err_str);                                              \
      return;                                                               \
    }                                                                       \
    return;                                                                 \
  } 
W
wangguibao 已提交
101 102 103 104 105 106 107 108 109

#define REGIST_ABTEST_OBJECT(D) \
  REGIST_FACTORY_OBJECT_IMPL(   \
      D, ::baidu::paddle_serving::sdk_cpp::ABTestRouterBase)

#define REGIST_ABTEST_OBJECT_WITH_TAG(D, T) \
  REGIST_FACTORY_OBJECT_IMPL_WITH_TAG(      \
      D, ::baidu::paddle_serving::sdk_cpp::ABTestRouterBase, T)

110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
#define REGIST_STUB_OBJECT_WITH_TAG(D, C, R, I, O, T)                       \
  __attribute__((constructor)) static void PDS_STR_CAT(GlobalRegistObject,  \
                                                       __LINE__)(void) {    \
    ::baidu::paddle_serving::sdk_cpp::Factory<                              \
        ::baidu::paddle_serving::sdk_cpp::StubImpl<D, C, R, I, O>,          \
        ::baidu::paddle_serving::sdk_cpp::Stub>* factory =                  \
        new (::std::nothrow)::baidu::paddle_serving::sdk_cpp::Factory<      \
            ::baidu::paddle_serving::sdk_cpp::StubImpl<D, C, R, I, O>,      \
            ::baidu::paddle_serving::sdk_cpp::Stub>();                      \
    if (factory == NULL ||                                                  \
        ::baidu::paddle_serving::sdk_cpp::FactoryPool<                      \
            ::baidu::paddle_serving::sdk_cpp::Stub>::instance()             \
                .register_factory(T, factory) != 0) {                       \
      char err_str[ERROR_STRING_LEN];                                       \
      snprintf(err_str, ERROR_STRING_LEN - 1,                               \
        "Failed regist factory: %s->Stub, tag: %s in macro!", #D, T);       \
      RAW_LOG(ERROR, err_str);                                              \
      return;                                                               \
    }                                                                       \
    return;                                                                 \
W
wangguibao 已提交
130
  }
W
sdk-cpp  
wangguibao 已提交
131 132 133 134 135

class Stub;
class EndpointRouterBase;
class VariantRouterBase;

W
wangguibao 已提交
136
template <typename B>
W
sdk-cpp  
wangguibao 已提交
137
class FactoryBase {
W
wangguibao 已提交
138 139 140
 public:
  virtual B* gen() = 0;
  virtual void del(B* obj) = 0;
W
sdk-cpp  
wangguibao 已提交
141 142
};

W
wangguibao 已提交
143
template <typename D, typename B>
W
sdk-cpp  
wangguibao 已提交
144
class Factory : public FactoryBase<B> {
W
wangguibao 已提交
145 146
 public:
  B* gen() { return new (std::nothrow) D(); }
W
sdk-cpp  
wangguibao 已提交
147

W
wangguibao 已提交
148
  void del(B* obj) { delete dynamic_cast<D*>(obj); }
W
sdk-cpp  
wangguibao 已提交
149 150
};

W
wangguibao 已提交
151
template <typename B>
W
sdk-cpp  
wangguibao 已提交
152
class FactoryPool {
W
wangguibao 已提交
153 154 155 156 157 158 159 160 161 162
 public:
  static FactoryPool<B>& instance() {
    static FactoryPool<B> singleton;
    return singleton;
  }

  int register_factory(const std::string& tag, FactoryBase<B>* factory) {
    typename std::map<std::string, FactoryBase<B>*>::iterator it =
        _pool.find(tag);
    if (it != _pool.end()) {
163 164 165 166
      char err_str[ERROR_STRING_LEN];
      snprintf(err_str, ERROR_STRING_LEN - 1, 
        "Insert duplicate with tag: %s", tag.c_str());
      RAW_LOG(ERROR, err_str);
W
wangguibao 已提交
167
      return -1;
W
sdk-cpp  
wangguibao 已提交
168 169
    }

W
wangguibao 已提交
170 171 172
    std::pair<typename std::map<std::string, FactoryBase<B>*>::iterator, bool>
        r = _pool.insert(std::make_pair(tag, factory));
    if (!r.second) {
173 174 175 176
      char err_str[ERROR_STRING_LEN];
      snprintf(err_str, ERROR_STRING_LEN - 1, 
        "Failed insert new factory with: %s", tag.c_str());
      RAW_LOG(ERROR, err_str);
W
wangguibao 已提交
177
      return -1;
W
sdk-cpp  
wangguibao 已提交
178 179
    }

W
wangguibao 已提交
180 181 182 183 184 185 186
    return 0;
  }

  B* generate_object(const std::string& tag) {
    typename std::map<std::string, FactoryBase<B>*>::iterator it =
        _pool.find(tag);
    if (it == _pool.end() || it->second == NULL) {
187 188 189 190 191
      char err_str[ERROR_STRING_LEN];
      snprintf(err_str, ERROR_STRING_LEN - 1, 
        "Not found factory pool, tag: %s, pool size: %u", 
        tag.c_str(), _pool.size());
      RAW_LOG(ERROR, err_str);
W
wangguibao 已提交
192
      return NULL;
W
sdk-cpp  
wangguibao 已提交
193 194
    }

W
wangguibao 已提交
195 196 197 198 199 200 201 202
    return it->second->gen();
  }

  template <typename D>
  void return_object(B* object) {
    Factory<D, B> factory;
    factory->del(object);
  }
W
sdk-cpp  
wangguibao 已提交
203

W
wangguibao 已提交
204 205
 private:
  std::map<std::string, FactoryBase<B>*> _pool;
W
sdk-cpp  
wangguibao 已提交
206 207 208 209 210 211 212 213
};

typedef FactoryPool<Stub> StubFactory;
typedef FactoryPool<brpc::CallMapper> CallMapperFactory;
typedef FactoryPool<brpc::ResponseMerger> ResponseMergerFactory;
typedef FactoryPool<EndpointRouterBase> EndpointRouterFactory;
typedef FactoryPool<VariantRouterBase> VariantRouterFactory;

W
wangguibao 已提交
214 215 216
}  // namespace sdk_cpp
}  // namespace paddle_serving
}  // namespace baidu