1 //  Copyright (c) 2011-2016 Hartmut Kaiser
2 //
3 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
4 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 
6 #if !defined(HPX_IOSTREAMS_SERVER_BUFFER_JUL_18_2014_0715PM)
7 #define HPX_IOSTREAMS_SERVER_BUFFER_JUL_18_2014_0715PM
8 
9 #include <hpx/config.hpp>
10 #include <hpx/lcos/local/recursive_mutex.hpp>
11 #include <hpx/runtime/serialization/serialization_fwd.hpp>
12 
13 #include <hpx/components/iostreams/export_definitions.hpp>
14 #include <hpx/components/iostreams/write_functions.hpp>
15 
16 #include <boost/swap.hpp>
17 
18 #include <iosfwd>
19 #include <memory>
20 #include <mutex>
21 #include <utility>
22 #include <vector>
23 
24 namespace hpx { namespace iostreams { namespace detail
25 {
26     struct buffer
27     {
28     protected:
29         typedef lcos::local::recursive_mutex mutex_type;
30 
31     public:
bufferhpx::iostreams::detail::buffer32         buffer()
33           : data_(new std::vector<char>),
34             mtx_(new mutex_type)
35         {}
36 
bufferhpx::iostreams::detail::buffer37         buffer(buffer const& rhs)
38           : data_(rhs.data_)
39           , mtx_(rhs.mtx_)
40         {}
41 
bufferhpx::iostreams::detail::buffer42         buffer(buffer && rhs)
43           : data_(std::move(rhs.data_))
44           , mtx_(std::move(rhs.mtx_))
45         {}
46 
operator =hpx::iostreams::detail::buffer47         buffer& operator=(buffer const& rhs)
48         {
49             if (this != &rhs)
50             {
51                 data_ = rhs.data_;
52                 mtx_ = rhs.mtx_;
53             }
54             return *this;
55         }
56 
operator =hpx::iostreams::detail::buffer57         buffer& operator=(buffer && rhs)
58         {
59             if (this != &rhs)
60             {
61                 data_ = std::move(rhs.data_);
62                 mtx_ = std::move(rhs.mtx_);
63             }
64             return *this;
65         }
66 
emptyhpx::iostreams::detail::buffer67         bool empty() const
68         {
69             std::lock_guard<mutex_type> l(*mtx_);
70             return empty_locked();
71         }
72 
empty_lockedhpx::iostreams::detail::buffer73         bool empty_locked() const
74         {
75             return !data_.get() || data_->empty();
76         }
77 
inithpx::iostreams::detail::buffer78         buffer init()
79         {
80             std::lock_guard<mutex_type> l(*mtx_);
81             return init_locked();
82         }
83 
init_lockedhpx::iostreams::detail::buffer84         buffer init_locked()
85         {
86             buffer b;
87             boost::swap(b.data_, data_);
88             return b;
89         }
90 
91         template <typename Char>
writehpx::iostreams::detail::buffer92         std::streamsize write(Char const* s, std::streamsize n)
93         {
94             std::lock_guard<mutex_type> l(*mtx_);
95             std::copy(s, s + n, std::back_inserter(*data_));
96             return n;
97         }
98 
99         template <typename Mutex>
writehpx::iostreams::detail::buffer100         void write(write_function_type const& f, Mutex& mtx)
101         {
102             std::unique_lock<mutex_type> l(*mtx_);
103             if (data_.get() && !data_->empty())
104             {
105                 std::shared_ptr<std::vector<char> > data(data_);
106                 data_.reset();
107                 l.unlock();
108 
109                 std::lock_guard<Mutex> ll(mtx);
110                 f(*data);
111             }
112         }
113 
114     private:
115         std::shared_ptr<std::vector<char> > data_;
116 
117     protected:
118         std::shared_ptr<mutex_type> mtx_;
119 
120     private:
121         friend class hpx::serialization::access;
122 
123         HPX_IOSTREAMS_EXPORT void save(
124             serialization::output_archive& ar, unsigned) const;
125         HPX_IOSTREAMS_EXPORT void load(
126             serialization::input_archive& ar, unsigned);
127 
128         HPX_SERIALIZATION_SPLIT_MEMBER();
129     };
130 }}}
131 
132 #endif
133