Performance optimisation for directors for classes passed by value
The directorin typemaps in the director methods now use std::move on the input parameter when copying the object from the stack to the heap prior to the callback into the target language, thereby taking advantage of move semantics if available.
This commit is contained in:
parent
e75095e6c5
commit
71cd6a38fe
24 changed files with 80 additions and 20 deletions
|
|
@ -28,6 +28,8 @@ public class runme
|
|||
break;
|
||||
};
|
||||
}
|
||||
if (director_pass_by_value.has_cplusplus11())
|
||||
Counter.check_counts(1, 0, 0, 1, 0, 1); // check move constructor called and just one destructor
|
||||
// bug was the passByVal 'global' object was destroyed after the call to virtualMethod had finished.
|
||||
int ret = runme.passByVal.getVal();
|
||||
if (ret != 0x12345678)
|
||||
|
|
|
|||
|
|
@ -1,14 +1,38 @@
|
|||
%module(directors="1") director_pass_by_value
|
||||
|
||||
#if defined(SWIGD)
|
||||
%rename(trace) debug;
|
||||
#endif
|
||||
|
||||
%director DirectorPassByValueAbstractBase;
|
||||
|
||||
%include "cpp11_move_only_helper.i"
|
||||
|
||||
%ignore PassedByValue::operator=;
|
||||
%ignore PassedByValue::PassedByValue(PassedByValue &&);
|
||||
|
||||
%inline %{
|
||||
class PassedByValue {
|
||||
int val;
|
||||
public:
|
||||
PassedByValue() { val = 0x12345678; }
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
int debug = false;
|
||||
struct PassedByValue {
|
||||
PassedByValue(int v = 0x12345678) { val = v; if (debug) cout << "PassedByValue(0x" << hex << val << ")" << " " << this << endl; Counter::normal_constructor++; }
|
||||
|
||||
PassedByValue(const PassedByValue &other) { val = other.val; if (debug) cout << "PassedByValue(const PassedByValue &)" << " " << this << " " << &other << endl; Counter::copy_constructor++;}
|
||||
PassedByValue & operator=(const PassedByValue &other) { val = other.val; if (debug) cout << "operator=(const PassedByValue &)" << " " << this << " " << &other << endl; Counter::copy_assignment++; return *this; }
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
PassedByValue(PassedByValue &&other) noexcept { val = other.val; if (debug) cout << "PassedByValue(PassedByValue &&)" << " " << this << endl; Counter::move_constructor++; }
|
||||
PassedByValue & operator=(PassedByValue &&other) noexcept { val = other.val; if (debug) cout << "operator=(PassedByValue &&)" << " " << this << endl; Counter::move_assignment++; return *this; }
|
||||
~PassedByValue() { if (debug) cout << "~PassedByValue()" << " " << this << endl; Counter::destructor++; }
|
||||
#endif
|
||||
|
||||
int getVal() { return val; }
|
||||
private:
|
||||
int val;
|
||||
};
|
||||
|
||||
|
||||
int doSomething(int x) {
|
||||
int yy[256];
|
||||
yy[0] =0x9876;
|
||||
|
|
@ -18,6 +42,7 @@ int doSomething(int x) {
|
|||
class DirectorPassByValueAbstractBase {
|
||||
public:
|
||||
virtual void virtualMethod(PassedByValue pbv) = 0;
|
||||
virtual void virtualConstMethod(const PassedByValue pbv) {}
|
||||
virtual ~DirectorPassByValueAbstractBase () {}
|
||||
};
|
||||
|
||||
|
|
@ -27,4 +52,12 @@ public:
|
|||
f.virtualMethod(PassedByValue());
|
||||
}
|
||||
};
|
||||
|
||||
bool has_cplusplus11() {
|
||||
#if __cplusplus >= 201103L
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
%}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ public class director_pass_by_value_runme {
|
|||
break;
|
||||
};
|
||||
}
|
||||
if (director_pass_by_value.has_cplusplus11())
|
||||
Counter.check_counts(1, 0, 0, 1, 0, 1); // check move constructor called and just one destructor
|
||||
// bug was the passByVal 'global' object was destroyed after the call to virtualMethod had finished.
|
||||
int ret = director_pass_by_value_runme.passByVal.getVal();
|
||||
if (ret != 0x12345678)
|
||||
|
|
|
|||
|
|
@ -14,10 +14,13 @@ let d =
|
|||
(director_pass_by_value_Derived)
|
||||
'()
|
||||
|
||||
let cpp11 = _has_cplusplus11 '() as bool
|
||||
|
||||
let _ =
|
||||
let caller = new_Caller '() in
|
||||
assert (caller -> call_virtualMethod (d) = C_void);
|
||||
assert (Array.length !passByVal = 1);
|
||||
(* TODO: only run if cpp11... let _ = _Counter_check_counts (C_list [C_int 0; C_int 0; C_int 0; C_int 1; C_int 0; C_int 1]) in*) (* check move constructor called and just one destructor *)
|
||||
let a = List.hd (fnhelper (!passByVal.(0))) in
|
||||
assert (a -> getVal () as int = 0x12345678);
|
||||
assert (a -> "~" () = C_void);
|
||||
|
|
|
|||
|
|
@ -14,6 +14,9 @@ class director_pass_by_value_Derived extends DirectorPassByValueAbstractBase {
|
|||
# bug was the passByVal global object was destroyed after the call to virtualMethod had finished.
|
||||
$caller = new Caller();
|
||||
$caller->call_virtualMethod(new director_pass_by_value_Derived());
|
||||
if (has_cplusplus11()) {
|
||||
Counter::check_counts(1, 0, 0, 1, 0, 1); # check move constructor called and just one destructor
|
||||
}
|
||||
$ret = $passByVal->getVal();
|
||||
if ($ret != 0x12345678) {
|
||||
check::fail("Bad return value, got " . dechex($ret));
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ class director_pass_by_value_Derived(director_pass_by_value.DirectorPassByValueA
|
|||
|
||||
# bug was the passByVal global object was destroyed after the call to virtualMethod had finished.
|
||||
director_pass_by_value.Caller().call_virtualMethod(director_pass_by_value_Derived())
|
||||
if director_pass_by_value.has_cplusplus11():
|
||||
director_pass_by_value.Counter.check_counts(1, 0, 0, 1, 0, 1) # check move constructor called and just one destructor
|
||||
ret = passByVal.getVal();
|
||||
if ret != 0x12345678:
|
||||
raise RuntimeError("Bad return value, got " + hex(ret))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue