this repo has no description
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2/*
3 * Main authors:
4 * Christian Schulte <schulte@gecode.org>
5 * Mikael Lagerkvist <lagerkvist@gecode.org>
6 *
7 * Copyright:
8 * Christian Schulte, 2008
9 * Mikael Lagerkvist, 2008
10 *
11 * This file is part of Gecode, the generic constraint
12 * development environment:
13 * http://www.gecode.org
14 *
15 * Permission is hereby granted, free of charge, to any person obtaining
16 * a copy of this software and associated documentation files (the
17 * "Software"), to deal in the Software without restriction, including
18 * without limitation the rights to use, copy, modify, merge, publish,
19 * distribute, sublicense, and/or sell copies of the Software, and to
20 * permit persons to whom the Software is furnished to do so, subject to
21 * the following conditions:
22 *
23 * The above copyright notice and this permission notice shall be
24 * included in all copies or substantial portions of the Software.
25 *
26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 *
34 */
35
36#include <gecode/kernel.hh>
37
38namespace Gecode { namespace Kernel {
39
40 /// %Brancher for calling a function
41 class FunctionBranch : public Brancher {
42 protected:
43 /// Minimal brancher description storing no information
44 class Description : public Choice {
45 public:
46 /// Initialize description for brancher \a b, number of alternatives \a a.
47 Description(const Brancher& b, unsigned int a);
48 /// Archive into \a e
49 virtual void archive(Archive& e) const;
50 };
51 /// Function to call
52 SharedData<std::function<void(Space& home)>> f;
53 /// Call function just once
54 bool done;
55 /// Construct brancher
56 FunctionBranch(Home home, std::function<void(Space& home)> f0);
57 /// Copy constructor
58 FunctionBranch(Space& home, FunctionBranch& b);
59 public:
60 /// Check status of brancher, return true if alternatives left
61 virtual bool status(const Space& home) const;
62 /// Return choice
63 virtual const Choice* choice(Space& home);
64 /// Return choice
65 virtual const Choice* choice(const Space& home, Archive& a);
66 /// Perform commit
67 virtual ExecStatus commit(Space& home, const Choice& ch, unsigned int a);
68 /// Print explanation
69 virtual void print(const Space&, const Choice&, unsigned int,
70 std::ostream& o) const;
71 /// Copy brancher
72 virtual Actor* copy(Space& home);
73 /// Post brancher
74 static void post(Home home, std::function<void(Space& home)> f);
75 /// Dispose brancher
76 virtual size_t dispose(Space& home);
77 };
78
79 forceinline
80 FunctionBranch::Description::Description(const Brancher& b, unsigned int a)
81 : Choice(b,a) {}
82 void
83 FunctionBranch::Description::archive(Archive& e) const {
84 Choice::archive(e);
85 }
86
87 forceinline
88 FunctionBranch::FunctionBranch(Home home,
89 std::function<void(Space& home)> f0)
90 : Brancher(home), f(f0), done(false) {
91 if (!f())
92 throw InvalidFunction("FunctionBranch::FunctionBranch");
93 home.notice(*this,AP_DISPOSE);
94 }
95 forceinline
96 FunctionBranch::FunctionBranch(Space& home, FunctionBranch& b)
97 : Brancher(home,b), f(b.f), done(b.done) {
98 }
99 bool
100 FunctionBranch::status(const Space&) const {
101 return !done;
102 }
103 const Choice*
104 FunctionBranch::choice(Space&) {
105 assert(!done);
106 return new Description(*this,1);
107 }
108 const Choice*
109 FunctionBranch::choice(const Space&, Archive&) {
110 return new Description(*this,1);
111 }
112 ExecStatus
113 FunctionBranch::commit(Space& home, const Choice&, unsigned int) {
114 done = true;
115 GECODE_VALID_FUNCTION(f());
116 f()(home);
117 return home.failed() ? ES_FAILED : ES_OK;
118 }
119 void
120 FunctionBranch::print(const Space&, const Choice&, unsigned int,
121 std::ostream& o) const {
122 o << "FunctionBranch()";
123 }
124 Actor*
125 FunctionBranch::copy(Space& home) {
126 return new (home) FunctionBranch(home,*this);
127 }
128 forceinline void
129 FunctionBranch::post(Home home, std::function<void(Space& home)> f) {
130 if (!f)
131 throw InvalidFunction("FunctionBranch::post");
132 (void) new (home) FunctionBranch(home,f);
133 }
134 size_t
135 FunctionBranch::dispose(Space& home) {
136 home.ignore(*this,AP_DISPOSE);
137 f.~SharedData<std::function<void(Space& home)>>();
138 (void) Brancher::dispose(home);
139 return sizeof(*this);
140 }
141
142}}
143
144namespace Gecode {
145
146 void
147 branch(Home home, std::function<void(Space& home)> f) {
148 Kernel::FunctionBranch::post(home,f);
149 }
150
151}
152
153// STATISTICS: kernel-branch