Skip to content

Commit a880643

Browse files
authored
Merge pull request #54 from stepfunc/feature/manual-dispose
Add manual dispose flag in the schema to remove IDisposable/AutoCloseable
2 parents 3b133e9 + d7339dc commit a880643

File tree

7 files changed

+74
-29
lines changed

7 files changed

+74
-29
lines changed

generators/dotnet-oo-bindgen/src/class.rs

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ pub(crate) fn generate(
2020
})?;
2121

2222
f.writeln(&format!("public sealed class {}", classname))?;
23-
if class.destructor.is_some() {
23+
if class.is_manual_destruction() {
2424
f.write(": IDisposable")?;
2525
}
2626

@@ -55,7 +55,13 @@ pub(crate) fn generate(
5555
}
5656

5757
if let Some(destructor) = &class.destructor {
58-
generate_destructor(f, &classname, destructor, lib)?;
58+
generate_destructor(
59+
f,
60+
&classname,
61+
destructor,
62+
class.is_manual_destruction(),
63+
lib,
64+
)?;
5965
f.newline()?;
6066
}
6167

@@ -171,23 +177,26 @@ fn generate_destructor(
171177
f: &mut dyn Printer,
172178
classname: &str,
173179
destructor: &NativeFunctionHandle,
180+
is_manual_destruction: bool,
174181
lib: &Library,
175182
) -> FormattingResult<()> {
176-
// Public Dispose method
177-
documentation(f, |f| xmldoc_print(f, &destructor.doc, lib))?;
183+
if is_manual_destruction {
184+
// Public Dispose method
185+
documentation(f, |f| xmldoc_print(f, &destructor.doc, lib))?;
178186

179-
f.writeln("public void Dispose()")?;
180-
blocked(f, |f| {
181-
f.writeln("Dispose(true);")?;
182-
f.writeln("GC.SuppressFinalize(this);")
183-
})?;
187+
f.writeln("public void Dispose()")?;
188+
blocked(f, |f| {
189+
f.writeln("Dispose(true);")?;
190+
f.writeln("GC.SuppressFinalize(this);")
191+
})?;
184192

185-
f.newline()?;
193+
f.newline()?;
194+
}
186195

187196
// Finalizer
188197
documentation(f, |f| {
189198
f.writeln("<summary>")?;
190-
f.writeln("Finalizer")?;
199+
f.write("Finalizer")?;
191200
f.write("</summary>")
192201
})?;
193202
f.writeln(&format!("~{}()", classname))?;

generators/java-oo-bindgen/src/java/class.rs

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ pub(crate) fn generate(
1616

1717
// Class definition
1818
f.writeln(&format!("public final class {}", classname))?;
19-
if class.destructor.is_some() {
19+
if class.is_manual_destruction() {
2020
f.write(" implements AutoCloseable")?;
2121
}
2222

@@ -39,7 +39,7 @@ pub(crate) fn generate(
3939
}
4040

4141
if let Some(destructor) = &class.destructor {
42-
generate_destructor(f, destructor, lib)?;
42+
generate_destructor(f, destructor, class.is_manual_destruction(), lib)?;
4343
f.newline()?;
4444
}
4545

@@ -145,25 +145,33 @@ fn generate_constructor(
145145
fn generate_destructor(
146146
f: &mut dyn Printer,
147147
destructor: &NativeFunctionHandle,
148+
is_manual_destruction: bool,
148149
lib: &Library,
149150
) -> FormattingResult<()> {
150-
documentation(f, |f| {
151-
// Print top-level documentation
152-
javadoc_print(f, &destructor.doc, lib)?;
153-
f.newline()?;
151+
if is_manual_destruction {
152+
documentation(f, |f| {
153+
// Print top-level documentation
154+
javadoc_print(f, &destructor.doc, lib)?;
155+
f.newline()?;
154156

155-
// Print each parameter value
156-
for param in destructor.parameters.iter().skip(1) {
157-
f.writeln(&format!("@param {} ", param.name.to_mixed_case()))?;
158-
docstring_print(f, &param.doc, lib)?;
159-
}
157+
// Print each parameter value
158+
for param in destructor.parameters.iter().skip(1) {
159+
f.writeln(&format!("@param {} ", param.name.to_mixed_case()))?;
160+
docstring_print(f, &param.doc, lib)?;
161+
}
160162

161-
Ok(())
162-
})?;
163+
Ok(())
164+
})?;
165+
}
166+
167+
if is_manual_destruction {
168+
// AutoCloseable implementation
169+
f.writeln("@Override")?;
170+
f.writeln("public void close()")?;
171+
} else {
172+
f.writeln("private void close()")?;
173+
}
163174

164-
// AutoCloseable implementation
165-
f.writeln("@Override")?;
166-
f.writeln("public void close()")?;
167175
blocked(f, |f| {
168176
f.writeln("if (this.disposed.getAndSet(true))")?;
169177
f.writeln(" return;")?;

oo-bindgen/src/class.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,18 @@ pub struct AsyncMethod {
3333
pub callback_param_name: String,
3434
}
3535

36+
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
37+
pub enum DestructionMode {
38+
/// Object is automatically deleted by the GC
39+
Automatic,
40+
/// Object is disposed of manually by calling a dispose()/close() method
41+
///
42+
/// For safety, if the user never calls the destruction method, the object
43+
/// will still be deleted by the GC at some point. However, it is
44+
/// strongly advised to take care of the destruction manually.
45+
Manual,
46+
}
47+
3648
/// Object-oriented class definition
3749
#[derive(Debug)]
3850
pub struct Class {
@@ -43,6 +55,7 @@ pub struct Class {
4355
pub static_methods: Vec<Method>,
4456
pub async_methods: Vec<AsyncMethod>,
4557
pub doc: Doc,
58+
pub destruction_mode: DestructionMode,
4659
}
4760

4861
impl Class {
@@ -54,6 +67,10 @@ impl Class {
5467
self.declaration.clone()
5568
}
5669

70+
pub fn is_manual_destruction(&self) -> bool {
71+
self.destruction_mode == DestructionMode::Manual && self.destructor.is_some()
72+
}
73+
5774
pub fn find_method<T: AsRef<str>>(&self, method_name: T) -> Option<&NativeFunctionHandle> {
5875
for method in &self.methods {
5976
if method.name == method_name.as_ref() {
@@ -88,6 +105,7 @@ pub struct ClassBuilder<'a> {
88105
static_methods: Vec<Method>,
89106
async_methods: Vec<AsyncMethod>,
90107
doc: Option<Doc>,
108+
destruction_mode: DestructionMode,
91109
}
92110

93111
impl<'a> ClassBuilder<'a> {
@@ -101,6 +119,7 @@ impl<'a> ClassBuilder<'a> {
101119
static_methods: Vec::new(),
102120
async_methods: Vec::new(),
103121
doc: None,
122+
destruction_mode: DestructionMode::Automatic,
104123
}
105124
}
106125

@@ -272,6 +291,11 @@ impl<'a> ClassBuilder<'a> {
272291
Ok(self)
273292
}
274293

294+
pub fn manual_destroy(mut self) -> Result<Self> {
295+
self.destruction_mode = DestructionMode::Manual;
296+
Ok(self)
297+
}
298+
275299
pub fn build(self) -> Result<ClassHandle> {
276300
let doc = match self.doc {
277301
Some(doc) => doc,
@@ -290,6 +314,7 @@ impl<'a> ClassBuilder<'a> {
290314
static_methods: self.static_methods,
291315
async_methods: self.async_methods,
292316
doc,
317+
destruction_mode: self.destruction_mode,
293318
});
294319

295320
self.lib

tests/bindings/dotnet/foo.Tests/CallbackTest.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public class CallbackTests
5959
[Fact]
6060
public void CallbackTest()
6161
{
62-
using (var cbSource = new CallbackSource())
62+
using(var cbSource = new CallbackSource())
6363
{
6464
var cb = new CallbackImpl();
6565
cbSource.SetInterface(cb);
@@ -78,7 +78,7 @@ public void CallbackTest()
7878

7979
private void singleRun(Counters counters)
8080
{
81-
using (var cbSource = new CallbackSource())
81+
using(var cbSource = new CallbackSource())
8282
{
8383
cbSource.SetInterface(new CallbackFinalizerCounterImpl(counters));
8484
cbSource.SetValue(76);

tests/foo-schema/src/callback.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ pub fn define(lib: &mut LibraryBuilder) -> Result<(), BindingError> {
101101
.method("SetInterface", &cbsource_set_interface)?
102102
.method("SetValue", &cbsource_set_value_func)?
103103
.method("SetDuration", &cbsource_set_duration_func)?
104+
.manual_destroy()?
104105
.doc("CallbackSource class")?
105106
.build()?;
106107

tests/foo-schema/src/class.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ pub fn define(lib: &mut LibraryBuilder) -> Result<(), BindingError> {
102102
.method("IncrementValue", &testclass_increment_value_func)?
103103
.async_method("GetValueAsync", &testclass_get_value_async_func)?
104104
.static_method("ConstructionCounter", &testclass_construction_counter)?
105+
.manual_destroy()?
105106
.doc("TestClass")?
106107
.build()?;
107108

tests/foo-schema/src/strings.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ pub fn define(lib: &mut LibraryBuilder) -> Result<(), BindingError> {
5252
.destructor(&stringclass_destroy_func)?
5353
.method("Echo", &stringclass_echo_func)?
5454
.static_method("GetLength", &stringclass_length_func)?
55+
.manual_destroy()?
5556
.doc("StringClass")?
5657
.build()?;
5758

0 commit comments

Comments
 (0)