Skip to content

Commit a52320a

Browse files
committed
Add autofree_rvalue
1 parent eaa99b0 commit a52320a

12 files changed

+400
-215
lines changed

include/flc.i

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ using std::size_t;
8383
* Linked into auto-generated file flibcpp_version.cpp
8484
************************/
8585

86-
%apply const char* { const char flibcpp_version[] };
86+
%apply char* { const char flibcpp_version[] };
8787
%fortranbindc flibcpp_version_major;
8888
%fortranbindc flibcpp_version_minor;
8989
%fortranbindc flibcpp_version_patch;

include/flc_random.i

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#endif
2828

2929
%rename(Engine) std::SWIG_MERSENNE_TWISTER;
30+
%fortran_autofree_rvalue(std::SWIG_MERSENNE_TWISTER);
3031

3132
namespace std {
3233
class SWIG_MERSENNE_TWISTER

include/flc_string.i

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
$result = ($1 == std::string::npos ? 0 : $1 + 1);
2323
}
2424

25+
// Automatically free temporary strings as appropriate
26+
%fortran_autofree_rvalue(std::string);
27+
2528
namespace std {
2629
class string {
2730
public:

include/flc_vector.i

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@
5151
%define %specialize_std_vector_pod(T)
5252
namespace std {
5353
template<> class vector<T> {
54+
// Automatically free temporary vectors as appropriate
55+
%fortran_autofree_rvalue(std::vector<T>);
56+
5457
SWIG_STD_VECTOR_COMMON(T, const T&)
5558
SWIG_STD_VECTOR_REF(T)
5659
%extend {
@@ -72,6 +75,7 @@ namespace std {
7275

7376
/* ------------------------------------------------------------------------- */
7477

78+
%fortran_autofree_rvalue(std::vector<std::string>);
7579
%extend std::vector<std::string> {
7680
void set_ref(size_type index, std::string& str) {
7781
SWIG_check_range(index, $self->size(),

src/flc.f90

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ function swigc_flibcpp_version_get() &
7171
contains
7272
! MODULE SUBPROGRAMS
7373

74-
subroutine SWIGTM_fout_const_SS_char_Sm_(imout, fout)
74+
subroutine SWIGTM_fout_char_Sm_(imout, fout)
7575
use, intrinsic :: ISO_C_BINDING
7676
type(SwigArrayWrapper), intent(in) :: imout
7777
character(kind=C_CHAR, len=:), allocatable, intent(out) :: fout
@@ -91,7 +91,7 @@ function get_serr() &
9191
type(SwigArrayWrapper) :: fresult
9292

9393
fresult = swigc_get_serr()
94-
call SWIGTM_fout_const_SS_char_Sm_(fresult, swig_result)
94+
call SWIGTM_fout_char_Sm_(fresult, swig_result)
9595
if (.false.) call SWIG_free(fresult%data)
9696
end function
9797

@@ -102,7 +102,7 @@ function get_flibcpp_version() &
102102
type(SwigArrayWrapper) :: fresult
103103

104104
fresult = swigc_flibcpp_version_get()
105-
call SWIGTM_fout_const_SS_char_Sm_(fresult, swig_result)
105+
call SWIGTM_fout_char_Sm_(fresult, swig_result)
106106
if (.false.) call SWIG_free(fresult%data)
107107
end function
108108

src/flcFORTRAN_wrap.cxx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ SWIGEXPORT SwigArrayWrapper _wrap_get_serr() {
345345
char *result = 0 ;
346346

347347
result = (char *)flc_get_serr();
348-
fresult.size = strlen(reinterpret_cast< const char* >(result));
348+
fresult.size = strlen((char*)(result));
349349
fresult.data = const_cast< char * >(result);
350350
return fresult;
351351
}
@@ -356,7 +356,7 @@ SWIGEXPORT SwigArrayWrapper _wrap_flibcpp_version_get() {
356356
char *result = 0 ;
357357

358358
result = (char *)(char *)flibcpp_version;
359-
fresult.size = strlen(reinterpret_cast< const char* >(result));
359+
fresult.size = strlen((char*)(result));
360360
fresult.data = const_cast< char * >(result);
361361
return fresult;
362362
}

src/flc_algorithmFORTRAN_wrap.cxx

Lines changed: 131 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,12 +216,22 @@ enum SwigMemFlags {
216216

217217
#define SWIG_check_nonnull(SWIG_CLASS_WRAPPER, TYPENAME, FNAME, FUNCNAME, RETURNNULL) \
218218
if (!(SWIG_CLASS_WRAPPER).cptr) { \
219-
SWIG_exception_impl(FUNCNAME, SWIG_TypeError, \
219+
SWIG_exception_impl(FUNCNAME, SWIG_NullReferenceError, \
220220
"Cannot pass null " TYPENAME " (class " FNAME ") " \
221221
"as a reference", RETURNNULL); \
222222
}
223223

224224

225+
namespace swig {
226+
enum AssignmentType {
227+
ASSIGNMENT_DEFAULT,
228+
ASSIGNMENT_NODESTRUCT,
229+
ASSIGNMENT_SMARTPTR
230+
};
231+
}
232+
233+
#define SWIGPOLICY_std_mt19937_64 swig::ASSIGNMENT_DEFAULT
234+
225235
#include <stdexcept>
226236

227237

@@ -458,6 +468,123 @@ SWIGINTERN SwigClassWrapper SwigClassWrapper_uninitialized() {
458468
return result;
459469
}
460470

471+
472+
namespace swig {
473+
474+
template<class T, AssignmentType A>
475+
struct DestructorPolicy {
476+
static SwigClassWrapper destroy(SwigClassWrapper self) {
477+
delete static_cast<T*>(self.cptr);
478+
return SwigClassWrapper_uninitialized();
479+
}
480+
};
481+
template<class T>
482+
struct DestructorPolicy<T, ASSIGNMENT_NODESTRUCT> {
483+
static SwigClassWrapper destroy(SwigClassWrapper) {
484+
SWIG_exception_impl("assignment", SWIG_TypeError, "Invalid assignment: class type has private destructor", return SwigClassWrapper_uninitialized());
485+
}
486+
};
487+
}
488+
489+
490+
namespace swig {
491+
492+
SWIGINTERN SwigClassWrapper capture(SwigClassWrapper other) {
493+
other.cmemflags &= ~SWIG_MEM_RVALUE;
494+
return other;
495+
}
496+
497+
template<class T, AssignmentType A>
498+
struct AssignmentPolicy {
499+
static SwigClassWrapper destroy(SwigClassWrapper self) {
500+
return DestructorPolicy<T, A>::destroy(self);
501+
}
502+
static SwigClassWrapper alias(SwigClassWrapper other) {
503+
SwigClassWrapper self = other;
504+
self.cmemflags &= ~SWIG_MEM_OWN;
505+
return self;
506+
}
507+
static SwigClassWrapper move_alias(SwigClassWrapper self, SwigClassWrapper other) {
508+
if (self.cmemflags & SWIG_MEM_OWN) {
509+
destroy(self);
510+
}
511+
return capture(other);
512+
}
513+
static SwigClassWrapper copy_alias(SwigClassWrapper self, SwigClassWrapper other) {
514+
if (self.cmemflags & SWIG_MEM_OWN) {
515+
destroy(self);
516+
}
517+
return capture(other);
518+
}
519+
};
520+
521+
template<class T>
522+
struct AssignmentPolicy<T, ASSIGNMENT_SMARTPTR> {
523+
static SwigClassWrapper destroy(SwigClassWrapper self) {
524+
return DestructorPolicy<T, ASSIGNMENT_SMARTPTR>::destroy(self);
525+
}
526+
static SwigClassWrapper alias(SwigClassWrapper other) {
527+
SwigClassWrapper self;
528+
self.cptr = new T(*static_cast<T*>(other.cptr));
529+
self.cmemflags = other.cmemflags | SWIG_MEM_OWN;
530+
return self;
531+
}
532+
static SwigClassWrapper move_alias(SwigClassWrapper self, SwigClassWrapper other) {
533+
self = copy_alias(self, other);
534+
self.cmemflags = other.cmemflags & ~SWIG_MEM_RVALUE;
535+
destroy(other);
536+
return self;
537+
}
538+
static SwigClassWrapper copy_alias(SwigClassWrapper self, SwigClassWrapper other) {
539+
// LHS and RHS should both 'own' their shared pointers
540+
T *pself = static_cast<T*>(self.cptr);
541+
T *pother = static_cast<T*>(other.cptr);
542+
*pself = *pother;
543+
return self;
544+
}
545+
};
546+
547+
} // end namespace swig
548+
549+
template<class T, swig::AssignmentType A>
550+
SWIGINTERN void SWIG_assign(SwigClassWrapper* self, SwigClassWrapper other) {
551+
typedef swig::AssignmentPolicy<T, A> Policy_t;
552+
553+
if (self->cptr == NULL) {
554+
/* LHS is unassigned */
555+
if (other.cmemflags & SWIG_MEM_RVALUE) {
556+
/* Capture pointer from RHS, clear 'moving' flag */
557+
*self = swig::capture(other);
558+
} else {
559+
/* Aliasing another class; clear ownership or copy smart pointer */
560+
*self = Policy_t::alias(other);
561+
}
562+
} else if (other.cptr == NULL) {
563+
/* Replace LHS with a null pointer */
564+
*self = Policy_t::destroy(*self);
565+
} else if (self->cptr == other.cptr) {
566+
/* Self-assignment: ignore */
567+
} else if (other.cmemflags & SWIG_MEM_RVALUE) {
568+
/* Transferred ownership from a variable that's about to be lost.
569+
* Move-assign and delete the transient data */
570+
*self = Policy_t::move_alias(*self, other);
571+
} else {
572+
/* RHS shouldn't be deleted, alias to LHS */
573+
*self = Policy_t::copy_alias(*self, other);
574+
}
575+
}
576+
577+
template<class T, swig::AssignmentType A>
578+
SWIGINTERN void SWIG_free_rvalue(SwigClassWrapper other) {
579+
typedef swig::AssignmentPolicy<T, A> Policy_t;
580+
if (other.cmemflags & SWIG_MEM_RVALUE
581+
&& other.cmemflags & SWIG_MEM_OWN) {
582+
/* We own *and* are being passed an expiring value */
583+
Policy_t::destroy(other);
584+
}
585+
}
586+
587+
461588
extern "C" {
462589
SWIGEXPORT void _wrap_sort__SWIG_1(SwigArrayWrapper *farg1) {
463590
int32_t *arg1 = (int32_t *) 0 ;
@@ -1123,6 +1250,7 @@ SWIGEXPORT void _wrap_shuffle__SWIG_1(SwigClassWrapper *farg1, SwigArrayWrapper
11231250
arg2 = (int32_t *)farg2->data;
11241251
arg3 = farg2->size;
11251252
shuffle< int32_t >(*arg1,arg2,arg3);
1253+
SWIG_free_rvalue< std::mt19937_64, SWIGPOLICY_std_mt19937_64 >(*farg1);
11261254
}
11271255

11281256

@@ -1136,6 +1264,7 @@ SWIGEXPORT void _wrap_shuffle__SWIG_2(SwigClassWrapper *farg1, SwigArrayWrapper
11361264
arg2 = (int64_t *)farg2->data;
11371265
arg3 = farg2->size;
11381266
shuffle< int64_t >(*arg1,arg2,arg3);
1267+
SWIG_free_rvalue< std::mt19937_64, SWIGPOLICY_std_mt19937_64 >(*farg1);
11391268
}
11401269

11411270

@@ -1149,6 +1278,7 @@ SWIGEXPORT void _wrap_shuffle__SWIG_3(SwigClassWrapper *farg1, SwigArrayWrapper
11491278
arg2 = (double *)farg2->data;
11501279
arg3 = farg2->size;
11511280
shuffle< double >(*arg1,arg2,arg3);
1281+
SWIG_free_rvalue< std::mt19937_64, SWIGPOLICY_std_mt19937_64 >(*farg1);
11521282
}
11531283

11541284

0 commit comments

Comments
 (0)