Skip to content

Adds "not borrowed" std.socket.Socket implementation#11040

Closed
denizzzka wants to merge 2 commits into
dlang:masterfrom
denizzzka:not_borrowed_socket
Closed

Adds "not borrowed" std.socket.Socket implementation#11040
denizzzka wants to merge 2 commits into
dlang:masterfrom
denizzzka:not_borrowed_socket

Conversation

@denizzzka

@denizzzka denizzzka commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Rationale

There is a case that is not covered by the std.socket.Socket:
When we get a ready-made socket_t from somewhere (from a 3rd-party library, for example), using it idiomatically in the D style, and after it we should just leave the socket "as is", because all other handling of this socket_t is performed by 3rd-party code.

Currently, if we want to do it this way, we have to duplicate the socket:
https://github.com/denizzzka/dpq2/blob/master/src/dpq2/connection.d#L227
and then Socket will close duplicate in desctructor without side-effects.

Solution

Socket code divided into Socket and its base SocketNotBorrowed classes. SocketNotBorrowed just not have destructor and not destroys passed socket_t.

In order not to break the documentation, it is need to separate documenting comments into a separate class. I made this in separate commit to convient reviewing.

Pre-review checklist

  • I have performed a self-review of my code.
  • If my PR fixes a bug or introduces a new feature, I have added thorough tests.

I think this case doesn't need additional testing because the solution to the problem is simply splitting Socket code into two parts, which are already covered by tests at the moment (I simply moved the constructors and destructor into a separate class)

  • If my changes are non-trivial and do not concern a reported issue, I have added a changelog entry.

@denizzzka denizzzka changed the title Adds "not borrowed" std.socket.Socket Adds "not borrowed" std.socket.Socket implementation Jun 17, 2026
@denizzzka denizzzka force-pushed the not_borrowed_socket branch from 51fef52 to 41a6393 Compare June 17, 2026 23:05
@denizzzka denizzzka marked this pull request as ready for review June 17, 2026 23:16
@denizzzka denizzzka requested a review from CyberShadow as a code owner June 17, 2026 23:16
@denizzzka denizzzka force-pushed the not_borrowed_socket branch 3 times, most recently from 1b56dc2 to 33ca83c Compare June 18, 2026 08:27
@CyberShadow

Copy link
Copy Markdown
Member

The usual solution for this is to set up strong ownership of the Socket (i.e. not rely on GC) and then call .release when it is no longer needed. It's quite unusual for a socket belonging to a live connection to be GC-collected, that would imply it was a live resource not connected to any logic in the program.

@denizzzka

Copy link
Copy Markdown
Contributor Author

@CyberShadow I don't know how to do this without breaking the existing interface. I'm not opposed to breaking API, but the last time I tried to fix by changing Socket API my PR was rejected.

@denizzzka denizzzka force-pushed the not_borrowed_socket branch from 33ca83c to 86ffa52 Compare June 18, 2026 10:51
@rikkimax

Copy link
Copy Markdown
Contributor

You can add overloads to say a constructor which takes a Flag instance.

@denizzzka

Copy link
Copy Markdown
Contributor Author

@rikkimax For some reason, I didn't like this idea last time, but I don't remember why.
Okay, I'll try to do that PR

@denizzzka

Copy link
Copy Markdown
Contributor Author

#11041

@CyberShadow

CyberShadow commented Jun 18, 2026

Copy link
Copy Markdown
Member

@CyberShadow I don't know how to do this without breaking the existing interface.

Not sure what you mean here. Here's an example of what I mean:

struct SocketThing
{
	typeof(scoped!Socket(socket_t.init, AddressFamily.init)) socket;

	this(socket_t s)
	{
		this.socket = scoped!Socket(s, AddressFamily.INET);
	}

	~this()
	{
		this.socket.release(); // do not close
	}
}

This way we can borrow socket handles without duplicating the handle or modifying the standard library.

@denizzzka

denizzzka commented Jun 18, 2026

Copy link
Copy Markdown
Contributor Author

@CyberShadow damn, yep! In fact we can just inherit Socket into our own class with own destructor calling release().

I still have a bad feeling because this solution requires knowledge of the internal structure of the Socket class, but I think the issue can be resolved without any Phobos changes. I don't think the Socket will change internals until Phobos v3 so it's acceptable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants