Skip to content

Commit 20b8093

Browse files
authored
Merge pull request #908 from owenv/ovoorhees/wrapper-lifetimes
Tie lifetimes of Swift wrappers to c++ command and tool objects
2 parents 783aec2 + 123e8fa commit 20b8093

File tree

5 files changed

+26
-13
lines changed

5 files changed

+26
-13
lines changed

examples/c-api/buildsystem/main.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ static llb_buildsystem_command_t*
9090
fancy_tool_create_command(void *context, const llb_data_t* name) {
9191
llb_buildsystem_external_command_delegate_t delegate;
9292
delegate.context = NULL;
93+
delegate.destroy_context = NULL;
9394
delegate.get_signature = NULL;
9495
delegate.configure = NULL;
9596
delegate.start = fancy_command_start;

products/libllbuild/BuildSystem-C-API.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,12 @@ class CAPITool : public Tool {
704704
return std::unique_ptr<Command>(
705705
(Command*) cAPIDelegate.create_custom_command(cAPIDelegate.context, key_p));
706706
}
707+
708+
~CAPITool() {
709+
if (cAPIDelegate.destroy_context) {
710+
cAPIDelegate.destroy_context(cAPIDelegate.context);
711+
}
712+
}
707713
};
708714

709715
class CAPIExternalCommand : public ExternalCommand {
@@ -1198,6 +1204,12 @@ class CAPIExternalCommand : public ExternalCommand {
11981204
}
11991205
return sig;
12001206
}
1207+
1208+
~CAPIExternalCommand() {
1209+
if (cAPIDelegate.destroy_context) {
1210+
cAPIDelegate.destroy_context(cAPIDelegate.context);
1211+
}
1212+
}
12011213
};
12021214

12031215
}

products/libllbuild/include/llbuild/buildsystem.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,10 @@ typedef struct llb_buildsystem_tool_delegate_t_ {
630630

631631
llb_buildsystem_command_t* (*create_custom_command)(void* context,
632632
const llb_build_key_t* key);
633+
634+
/// Callback a client may use to tear down data structures associated with the context
635+
/// pointer.
636+
void (*destroy_context)(void* context);
633637

634638
// FIXME: Support dynamic tool commands.
635639
} llb_buildsystem_tool_delegate_t;
@@ -771,6 +775,10 @@ typedef struct llb_buildsystem_external_command_delegate_t_ {
771775
bool (*is_result_valid)(void* context,
772776
llb_buildsystem_command_t* command,
773777
const llb_build_value* value);
778+
779+
/// Callback a client may use to tear down data structures associated with the context
780+
/// pointer.
781+
void (*destroy_context)(void* context);
774782

775783
} llb_buildsystem_external_command_delegate_t;
776784

products/llbuildSwift/BuildSystemBindings.swift

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -168,11 +168,6 @@ private final class ToolWrapper {
168168
self.tool = tool
169169
}
170170

171-
/// The owning list of all created commands.
172-
//
173-
// FIXME: This is unfortunate, we should be able to destroy these naturally.
174-
private var commandWrappers: [CommandWrapper] = []
175-
176171
func createCommand(_ name: UnsafePointer<llb_data_t>) -> OpaquePointer? {
177172
let command = tool.createCommand(stringFromData(name.pointee)) as ExternalCommand?
178173
return command.map { command in buildCommand(name, command) } ?? nil
@@ -198,9 +193,9 @@ private final class ToolWrapper {
198193

199194
private func buildCommand(_ name: UnsafePointer<llb_data_t>, _ command: ExternalCommand) -> OpaquePointer? {
200195
let wrapper = CommandWrapper(command: command)
201-
self.commandWrappers.append(wrapper)
202196
var _delegate = llb_buildsystem_external_command_delegate_t()
203-
_delegate.context = Unmanaged.passUnretained(wrapper).toOpaque()
197+
_delegate.context = Unmanaged.passRetained(wrapper).toOpaque()
198+
_delegate.destroy_context = { Unmanaged<CommandWrapper>.fromOpaque(UnsafeRawPointer($0!)).release() }
204199
_delegate.configure = { BuildSystem.toCommandWrapper($0!).configure($1!, $2!, $3!, $4!) }
205200
_delegate.get_signature = { return BuildSystem.toCommandWrapper($0!).getSignature($1!, $2!) }
206201
_delegate.start = { return BuildSystem.toCommandWrapper($0!).start($1!, $2!, $3) }
@@ -1253,10 +1248,6 @@ public final class BuildSystem {
12531248
return fsGetFileInfo(path, info)
12541249
}
12551250

1256-
/// The owning list of all created tools.
1257-
//
1258-
// FIXME: This is unfortunate, we should be able to destroy these naturally.
1259-
private var toolWrappers: [ToolWrapper] = []
12601251
private func lookupTool(_ name: UnsafePointer<llb_data_t>) -> OpaquePointer? {
12611252
// Look up the named tool.
12621253
guard let tool = delegate.lookupTool(stringFromData(name.pointee)) else {
@@ -1265,9 +1256,9 @@ public final class BuildSystem {
12651256

12661257
// If we got a tool, save it and create an appropriate low-level instance.
12671258
let wrapper = ToolWrapper(tool: tool)
1268-
self.toolWrappers.append(wrapper)
12691259
var _delegate = llb_buildsystem_tool_delegate_t()
1270-
_delegate.context = Unmanaged.passUnretained(wrapper).toOpaque()
1260+
_delegate.context = Unmanaged.passRetained(wrapper).toOpaque()
1261+
_delegate.destroy_context = { Unmanaged<CommandWrapper>.fromOpaque(UnsafeRawPointer($0!)).release() }
12711262
_delegate.create_command = { return BuildSystem.toToolWrapper($0!).createCommand($1!) }
12721263
_delegate.create_custom_command = { return BuildSystem.toToolWrapper($0!).createCustomCommand($1!) }
12731264

unittests/CAPI/BuildSystem-C-API.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ static llb_buildsystem_command_t*
141141
depinfo_tester_tool_create_command(void *context, const llb_data_t* name) {
142142
llb_buildsystem_external_command_delegate_t delegate;
143143
delegate.context = NULL;
144+
delegate.destroy_context = NULL;
144145
delegate.get_signature = NULL;
145146
delegate.configure = NULL;
146147
delegate.start = depinfo_tester_command_start;

0 commit comments

Comments
 (0)