smartpointer.go 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. package frankenphp
  2. // #include <stdlib.h>
  3. import "C"
  4. import (
  5. "runtime/cgo"
  6. "unsafe"
  7. )
  8. /*
  9. FrankenPHP is fairly complex because it shuffles handles/requests/contexts
  10. between C and Go. This simplifies the lifecycle management of per-request
  11. structures by allowing us to hold references until the end of the request
  12. and ensure they are always cleaned up.
  13. */
  14. // PointerList A list of pointers that can be freed at a later time
  15. type pointerList struct {
  16. Pointers []unsafe.Pointer
  17. }
  18. // HandleList A list of pointers that can be freed at a later time
  19. type handleList struct {
  20. Handles []cgo.Handle
  21. }
  22. // AddHandle Call when registering a handle for the very first time
  23. func (h *handleList) AddHandle(handle cgo.Handle) {
  24. h.Handles = append(h.Handles, handle)
  25. }
  26. // AddPointer Call when creating a request-level C pointer for the very first time
  27. func (p *pointerList) AddPointer(ptr unsafe.Pointer) {
  28. p.Pointers = append(p.Pointers, ptr)
  29. }
  30. // FreeAll frees all C pointers
  31. func (p *pointerList) FreeAll() {
  32. for _, ptr := range p.Pointers {
  33. C.free(ptr)
  34. }
  35. p.Pointers = nil // To avoid dangling pointers
  36. }
  37. // FreeAll frees all handles
  38. func (h *handleList) FreeAll() {
  39. for _, p := range h.Handles {
  40. p.Delete()
  41. }
  42. }
  43. // Pointers Get a new list of pointers
  44. func Pointers() *pointerList {
  45. return &pointerList{
  46. Pointers: make([]unsafe.Pointer, 0),
  47. }
  48. }
  49. // Handles Get a new list of handles
  50. func Handles() *handleList {
  51. return &handleList{
  52. Handles: make([]cgo.Handle, 0, 8),
  53. }
  54. }