It is awkward that Task has an
destroy(), but otherwise are expected to be tied to a single job. The main source of this issue is that jobs don't have any lifecycle control.
- Have a thread and weak reference queue waiting for jobs to be GCed, and then run the destruction logic for each task.
- Make job creation handled by private constructors of the scheduler, so then running a job once destroys everything at the end, and repeated job schedules aren't destroyed until explicitly terminated.
- Remove lifecycle control from Task, and implement reference queuing logic for decorated properties.
The first option is the worst in that it requires a bunch of work with relatively little interface gain. The second is pretty good and might be acceptable. The reason I'm leaning towards three is that it:
- simplifies the Task and Job interfaces since neither care about
- the lifecycle for tasks returned from
process()are cleaner since I don't need to document that their lifecycle methods would normally be ignored
- it also makes other property decoration cases safe as well
The only downside is it doesn't allow for more generic cleanup logic for different types of controllers, but honestly I haven't yet found a need other than undecorating of properties and letting the GC handle the rest.