Multiscale Universal Interface  2.0
A Concurrent Framework for Coupling Heterogeneous Solvers
spatial_storage.h
Go to the documentation of this file.
1 /*****************************************************************************
2 * Multiscale Universal Interface Code Coupling Library *
3 * *
4 * Copyright (C) 2019 Y. H. Tang, S. Kudo, X. Bian, Z. Li, G. E. Karniadakis *
5 * *
6 * This software is jointly licensed under the Apache License, Version 2.0 *
7 * and the GNU General Public License version 3, you may use it according *
8 * to either. *
9 * *
10 * ** Apache License, version 2.0 ** *
11 * *
12 * Licensed under the Apache License, Version 2.0 (the "License"); *
13 * you may not use this file except in compliance with the License. *
14 * You may obtain a copy of the License at *
15 * *
16 * http://www.apache.org/licenses/LICENSE-2.0 *
17 * *
18 * Unless required by applicable law or agreed to in writing, software *
19 * distributed under the License is distributed on an "AS IS" BASIS, *
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
21 * See the License for the specific language governing permissions and *
22 * limitations under the License. *
23 * *
24 * ** GNU General Public License, version 3 ** *
25 * *
26 * This program is free software: you can redistribute it and/or modify *
27 * it under the terms of the GNU General Public License as published by *
28 * the Free Software Foundation, either version 3 of the License, or *
29 * (at your option) any later version. *
30 * *
31 * This program is distributed in the hope that it will be useful, *
32 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
33 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
34 * GNU General Public License for more details. *
35 * *
36 * You should have received a copy of the GNU General Public License *
37 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
38 *****************************************************************************/
39 
47 #define SPATIAL_STORAGE_H
48 
49 #include <exception>
50 #include <mutex>
51 #include "dynstorage.h"
52 #include "virtual_container.h"
53 
54 namespace mui {
55 
56 template<typename BIN, typename STORAGE, typename CONFIG>
58 private: // type definitions
59  using storage_t = STORAGE;
60 public:
61  using point_type = typename CONFIG::point_type;
62  using EXCEPTION = typename CONFIG::EXCEPTION;
63 
64 private: // functors
65  struct insert_ {
66  template<typename T> void operator()( T& t ){
67  T& rhs = storage_cast<T&>(st);
68  t.insert(t.end(), std::make_move_iterator(rhs.begin()), std::make_move_iterator(rhs.end()));
69  }
70  storage_t st;
71  };
72  struct construct_ {
73  template<typename T> void operator()(T& t){ ::new(ptr) BIN(t); }
74  void* ptr;
75  };
76 public:
77  spatial_storage() noexcept {
78  is_bin_ = false;
79  }
81  destroy_if_bin_();
82  }
83  spatial_storage( const spatial_storage& rhs ): data_(rhs.data_) {
84  is_bin_.store(rhs.is_bin_.load());
85  if( rhs.is_built() ) ::new(&bin_) BIN(rhs.bin_);
86  }
87  spatial_storage( spatial_storage&& rhs ) noexcept : data_(std::move(rhs.data_)) {
88  is_bin_.store(rhs.is_bin_.load());
89  if( rhs.is_built() ) ::new(&bin_) BIN(std::move(rhs.bin_));
90  rhs.destroy_if_bin_();
91  }
92  spatial_storage( storage_t rhs ): data_(std::move(rhs)) {
93  is_bin_ = false;
94  }
96  rhs.swap(*this);
97  return *this;
98  }
99 
100  void swap( spatial_storage& rhs ) noexcept(noexcept(BIN(std::move(rhs.bin_)))) {
101  data_.swap(rhs.data_);
102  if( is_bin_ && rhs.is_bin_ ) bin_.swap(rhs.bin_);
103  else if( is_bin_ && !rhs.is_bin_ ) {
104  ::new(&(rhs.bin_)) BIN(std::move(bin_));
105  rhs.is_bin_ = true;
106  destroy_if_bin_();
107  } else if( !is_bin_ && rhs.is_bin_ ) {
108  ::new(&(bin_)) BIN(std::move(rhs.bin_));
109  is_bin_ = true;
110  rhs.destroy_if_bin_();
111  }
112  }
113 
114  // no lock internally; it's job of uniface because
115  // we need more large lock if there is no rw-lock.
116  template<typename REGION, typename FOCUS, typename SAMPLER, typename ... ADDITIONAL>
117  typename SAMPLER::OTYPE
118  query(const REGION& reg, const FOCUS& f, SAMPLER& s, ADDITIONAL && ... additional) const {
119  using vec = std::vector<std::pair<point_type,typename SAMPLER::ITYPE> >;
120 
121  if( data_.empty() )
122  return s.filter( f, virtual_container<typename SAMPLER::ITYPE,CONFIG>(vec(), std::vector<bool>()), additional... );
123  if( !is_built() ) EXCEPTION(std::logic_error("MUI Error [spatial_storage.h]: Query error, "
124  "bin structure not built yet."));
125 
126  const vec& st = storage_cast<const vec&>(data_);
127 
128  return s.filter( f, virtual_container<typename SAMPLER::ITYPE,CONFIG>(st, bin_.query(reg)), additional...);
129  }
130 
131  void build() {
132  if( is_built() ) EXCEPTION(std::logic_error("MUI Error [spatial_storage.h]: Build error, cannot build bin structure twice."));
133  if( !data_.empty() ) {
134  data_.apply_visitor(construct_{static_cast<void*>(&bin_)});
135  is_bin_ = true;
136  }
137  }
138 
139  template<typename FOCUS, typename SAMPLER, typename ...ADDITIONAL>
140  typename SAMPLER::OTYPE
141  build_and_query_ts(const FOCUS& f, SAMPLER& s, ADDITIONAL && ... additional) {
142  // this method is thread-safe. other methods are not.
143  {
144  std::unique_lock<std::mutex> lock(mutex_);
145  if( !is_built() ) build();
146  }
147 
148  return query(s.support(f, bin_.domain_size()).bbox(), f, s, additional...);
149  }
150 
151  void insert( storage_t storage ) {
152  destroy_if_bin_();
153  if( !storage ) return;
154  if( !data_ ) data_ = std::move(storage);
155  else if( data_.which() == storage.which() ) data_.apply_visitor(insert_{storage});
156  else EXCEPTION(bad_storage_id("MUI Error [spatial_storage.h]: Insert error. Type doesn't match."));
157  }
158 
159  template<typename TYPE>
160  const std::vector<std::pair<point_type,TYPE> >& return_data() {
161  return storage_cast<const std::vector<std::pair<point_type,TYPE> >& >(data_);
162  }
163 
164 
165  bool is_built() const { return is_bin_; }
166  bool empty() const { return data_.empty(); }
167 private:
168  void destroy_if_bin_() {
169  if( is_built() ) {
170  bin_.~BIN();
171  is_bin_ = false;
172  }
173  }
174 
175  storage_t data_;
176 
177  std::atomic<bool> is_bin_;
178  union {
179  char nodata_ = '\0';
180  BIN bin_;
181  };
182  mutable std::mutex mutex_;
183 };
184 }
185 
186 #define SPATIAL_STORAGE_H
Definition: spatial_storage.h:57
spatial_storage(storage_t rhs)
Definition: spatial_storage.h:92
SAMPLER::OTYPE query(const REGION &reg, const FOCUS &f, SAMPLER &s, ADDITIONAL &&... additional) const
Definition: spatial_storage.h:118
typename CONFIG::point_type point_type
Definition: spatial_storage.h:61
bool is_built() const
Definition: spatial_storage.h:165
char nodata_
Definition: spatial_storage.h:179
typename CONFIG::EXCEPTION EXCEPTION
Definition: spatial_storage.h:62
~spatial_storage()
Definition: spatial_storage.h:80
void swap(spatial_storage &rhs) noexcept(noexcept(BIN(std::move(rhs.bin_))))
Definition: spatial_storage.h:100
spatial_storage(const spatial_storage &rhs)
Definition: spatial_storage.h:83
BIN bin_
Definition: spatial_storage.h:180
spatial_storage(spatial_storage &&rhs) noexcept
Definition: spatial_storage.h:87
spatial_storage & operator=(spatial_storage rhs)
Definition: spatial_storage.h:95
void insert(storage_t storage)
Definition: spatial_storage.h:151
void build()
Definition: spatial_storage.h:131
bool empty() const
Definition: spatial_storage.h:166
SAMPLER::OTYPE build_and_query_ts(const FOCUS &f, SAMPLER &s, ADDITIONAL &&... additional)
Definition: spatial_storage.h:141
spatial_storage() noexcept
Definition: spatial_storage.h:77
const std::vector< std::pair< point_type, TYPE > > & return_data()
Definition: spatial_storage.h:160
Definition: virtual_container.h:97
Implementation of a compound dynamic data structure used throughout MUI.
T
Definition: dim.h:363
Definition: comm.h:54
Definition: dynstorage.h:62
Definition: dynstorage.h:146
id_t which() const
Definition: dynstorage.h:208
Provides a virtual container interface that is used to wrap around data structures created by dynstor...